]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-17116 migrate regulatory report trigger to /api/features/list
authorMatteo Mara <matteo.mara@sonarsource.com>
Thu, 22 Sep 2022 10:41:42 +0000 (12:41 +0200)
committersonartech <sonartech@sonarsource.com>
Fri, 23 Sep 2022 20:02:51 +0000 (20:02 +0000)
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/ProjectInformationRenderer.tsx
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/ProjectInformationRenderer-test.tsx
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/ProjectInformation-test.tsx.snap
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/ProjectInformationRenderer-test.tsx.snap
server/sonar-web/src/main/js/types/appstate.ts
server/sonar-web/src/main/js/types/features.ts
server/sonar-webserver-webapi/src/main/java/org/sonar/server/ui/ws/GlobalAction.java
server/sonar-webserver-webapi/src/main/resources/org/sonar/server/ui/ws/global-example.json
server/sonar-webserver-webapi/src/test/java/org/sonar/server/ui/ws/GlobalActionTest.java

index 3d61193be3df4a7a034e3024b8afc16202179e72..8402bd8e2776b1343e24a1bf864538d1e9fc661a 100644 (file)
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import * as React from 'react';
+import PrivacyBadgeContainer from '../../../../../components/common/PrivacyBadgeContainer';
 import { ButtonLink } from '../../../../../components/controls/buttons';
 import ModalButton from '../../../../../components/controls/ModalButton';
-import PrivacyBadgeContainer from '../../../../../components/common/PrivacyBadgeContainer';
 import { translate } from '../../../../../helpers/l10n';
+import { BranchLike } from '../../../../../types/branch-like';
 import { ComponentQualifier } from '../../../../../types/component';
+import { Feature } from '../../../../../types/features';
 import { Component, Measure } from '../../../../../types/types';
+import withAvailableFeatures, {
+  WithAvailableFeaturesProps
+} from '../../../available-features/withAvailableFeatures';
 import DrawerLink from './DrawerLink';
 import MetaKey from './meta/MetaKey';
 import MetaLinks from './meta/MetaLinks';
@@ -33,12 +38,8 @@ import MetaSize from './meta/MetaSize';
 import MetaTags from './meta/MetaTags';
 import { ProjectInformationPages } from './ProjectInformationPages';
 import RegulatoryReportModal from './projectRegulatoryReport/RegulatoryReportModal';
-import withAppStateContext from '../../../app-state/withAppStateContext';
-import { AppState } from '../../../../../types/appstate';
-import { BranchLike } from '../../../../../types/branch-like';
 
-export interface ProjectInformationRendererProps {
-  appState: AppState;
+export interface ProjectInformationRendererProps extends WithAvailableFeaturesProps {
   canConfigureNotifications: boolean;
   canUseBadges: boolean;
   component: Component;
@@ -49,14 +50,7 @@ export interface ProjectInformationRendererProps {
 }
 
 export function ProjectInformationRenderer(props: ProjectInformationRendererProps) {
-  const {
-    canConfigureNotifications,
-    canUseBadges,
-    component,
-    measures = [],
-    appState,
-    branchLike
-  } = props;
+  const { canConfigureNotifications, canUseBadges, component, measures = [], branchLike } = props;
 
   const heading = React.useRef<HTMLHeadingElement>(null);
   const isApp = component.qualifier === ComponentQualifier.Application;
@@ -68,6 +62,8 @@ export function ProjectInformationRenderer(props: ProjectInformationRendererProp
     }
   }, [heading]);
 
+  const regulatoryReportFeatureEnabled = props.hasFeature(Feature.RegulatoryReport);
+
   return (
     <>
       <div>
@@ -139,27 +135,26 @@ export function ProjectInformationRenderer(props: ProjectInformationRendererProp
               />
             </li>
           )}
-          {component.qualifier === ComponentQualifier.Project &&
-            appState.regulatoryReportFeatureEnabled && (
-              <li className="big-padded bordered-bottom">
-                <ModalButton
-                  modal={({ onClose }) => (
-                    <RegulatoryReportModal
-                      component={component}
-                      branchLike={branchLike}
-                      onClose={onClose}
-                    />
-                  )}>
-                  {({ onClick }) => (
-                    <ButtonLink onClick={onClick}>{translate('regulatory_report.page')}</ButtonLink>
-                  )}
-                </ModalButton>
-              </li>
-            )}
+          {component.qualifier === ComponentQualifier.Project && regulatoryReportFeatureEnabled && (
+            <li className="big-padded bordered-bottom">
+              <ModalButton
+                modal={({ onClose }) => (
+                  <RegulatoryReportModal
+                    component={component}
+                    branchLike={branchLike}
+                    onClose={onClose}
+                  />
+                )}>
+                {({ onClick }) => (
+                  <ButtonLink onClick={onClick}>{translate('regulatory_report.page')}</ButtonLink>
+                )}
+              </ModalButton>
+            </li>
+          )}
         </ul>
       </div>
     </>
   );
 }
 
-export default withAppStateContext(React.memo(ProjectInformationRenderer));
+export default withAvailableFeatures(React.memo(ProjectInformationRenderer));
index 0aa6ee2acbf4b64d61d07207839c9b5d3964b50a..bec0684abeefc66980ff15fa916b52d1c983381b 100644 (file)
@@ -20,7 +20,6 @@
 import { shallow } from 'enzyme';
 import * as React from 'react';
 import { mockComponent } from '../../../../../../helpers/mocks/component';
-import { mockAppState } from '../../../../../../helpers/testMocks';
 import {
   ProjectInformationRenderer,
   ProjectInformationRendererProps
@@ -65,12 +64,10 @@ it('should handle missing quality profiles and quality gates', () => {
   ).toMatchSnapshot();
 });
 
-it('should render app correctly when regulatoryReportFeatureEnabled is false', () => {
+it('should render app correctly when regulatoryReport feature is not enabled', () => {
   expect(
     shallowRender({
-      appState: mockAppState({
-        regulatoryReportFeatureEnabled: false
-      })
+      hasFeature: jest.fn().mockReturnValue(false)
     })
   ).toMatchSnapshot();
 });
@@ -87,9 +84,7 @@ it('should set focus on the heading when rendered', () => {
 function shallowRender(props: Partial<ProjectInformationRendererProps> = {}) {
   return shallow(
     <ProjectInformationRenderer
-      appState={mockAppState({
-        regulatoryReportFeatureEnabled: true
-      })}
+      hasFeature={jest.fn().mockReturnValue(true)}
       canConfigureNotifications={true}
       canUseBadges={true}
       component={mockComponent({ qualifier: 'TRK', visibility: 'public' })}
index a010a9957f3e4418b9dd87e1dd91001c7bd3f062..e413632b09733526b1ed74fda1335ad743eb3b85 100644 (file)
@@ -2,7 +2,7 @@
 
 exports[`should render correctly: default 1`] = `
 <Fragment>
-  <withAppStateContext(Component)
+  <withAvailableFeaturesContext(Component)
     canConfigureNotifications={false}
     canUseBadges={true}
     component={
@@ -64,7 +64,7 @@ exports[`should render correctly: default 1`] = `
 
 exports[`should render correctly: logged in user 1`] = `
 <Fragment>
-  <withAppStateContext(Component)
+  <withAvailableFeaturesContext(Component)
     canConfigureNotifications={true}
     canUseBadges={true}
     component={
@@ -155,7 +155,7 @@ exports[`should render correctly: logged in user 1`] = `
 
 exports[`should render correctly: measures loaded 1`] = `
 <Fragment>
-  <withAppStateContext(Component)
+  <withAvailableFeaturesContext(Component)
     canConfigureNotifications={false}
     canUseBadges={true}
     component={
@@ -231,7 +231,7 @@ exports[`should render correctly: measures loaded 1`] = `
 
 exports[`should render correctly: private 1`] = `
 <Fragment>
-  <withAppStateContext(Component)
+  <withAvailableFeaturesContext(Component)
     canConfigureNotifications={false}
     canUseBadges={true}
     component={
index 078dd259d5700796d58b620ce210eee893856a08..14a8202a9b0cc83bbe097005ef4402440163e94c 100644 (file)
@@ -390,7 +390,7 @@ exports[`should render an app correctly: default 1`] = `
 </Fragment>
 `;
 
-exports[`should render app correctly when regulatoryReportFeatureEnabled is false 1`] = `
+exports[`should render app correctly when regulatoryReport feature is not enabled 1`] = `
 <Fragment>
   <div>
     <h2
index 306de8d6ac67174fe0b1f713a80d02b7851af0d4..625551487645725c8aeb560c32892788a2070da0 100644 (file)
@@ -39,5 +39,4 @@ export interface AppState {
   standalone?: boolean;
   version: string;
   webAnalyticsJsPath?: string;
-  regulatoryReportFeatureEnabled?: boolean;
 }
index c21b1f68a1f4738f249148f77b8adedd2150e4ee..cb4210542bcbfa0956209cc0c90527742c35ca4d 100644 (file)
@@ -19,5 +19,6 @@
  */
 
 export enum Feature {
-  MonoRepositoryPullRequestDecoration = 'monorepo'
+  MonoRepositoryPullRequestDecoration = 'monorepo',
+  RegulatoryReport = 'regulatory-reports'
 }
index 658cf49b49f1a2d393981420517af3b5557085d5..e08588d7149bc95476725c8c3c6483aba3a5b5cb 100644 (file)
@@ -69,8 +69,6 @@ public class GlobalAction implements NavigationWsAction, Startable {
     SONAR_LF_GRAVATAR_SERVER_URL,
     RATING_GRID,
     DEVELOPER_AGGREGATED_INFO_DISABLED);
-
-  private static final String REGULATORY_REPORT_FEATURE_ENABLED_FLAG  = "regulatoryReportFeatureEnabled";
   
   private final Map<String, String> systemSettingValuesByKey;
 
@@ -143,7 +141,6 @@ public class GlobalAction implements NavigationWsAction, Startable {
       writeInstanceUsesDefaultAdminCredentials(json);
       writeMultipleAlmEnabled(json);
       writeProjectImportFeature(json);
-      writeRegulatoryReportFeature(json);
       editionProvider.get().ifPresent(e -> json.prop("edition", e.name().toLowerCase(Locale.ENGLISH)));
       writeNeedIssueSync(json);
       json.prop("standalone", webServer.isStandalone());
@@ -226,12 +223,6 @@ public class GlobalAction implements NavigationWsAction, Startable {
     webAnalyticsLoader.getUrlPathToJs().ifPresent(p -> json.prop("webAnalyticsJsPath", p));
   }
 
-  private void writeRegulatoryReportFeature(JsonWriter json) {
-    Edition edition = editionProvider.get().orElse(null);
-    boolean isEnabled = isEditionEEorDCE(edition);
-    json.prop(REGULATORY_REPORT_FEATURE_ENABLED_FLAG, isEnabled);
-  }
-
   private static boolean isEditionEEorDCE(@Nullable Edition edition) {
     return Arrays.asList(ENTERPRISE, DATACENTER).contains(edition);
   }
index a9779b55d4138950aceb0026c1dcf408220e593a..7a110f13d789b17f4bfd269264a066dd831001cb 100644 (file)
@@ -27,7 +27,6 @@
   "productionDatabase": true,
   "branchesEnabled": false,
   "projectImportFeatureEnabled": false,
-  "regulatoryReportFeatureEnabled": false,
   "canAdmin": false,
   "standalone": true,
   "edition": "community"
index 1d8d40662f04a654940776700c41f62cf26fbcea..b37184ad49b45bc4bcfd980c1fe7ce0651ea8275 100644 (file)
@@ -272,29 +272,6 @@ public class GlobalActionTest {
     assertJson(call()).isSimilarTo("{\"needIssueSync\": false}");
   }
 
-  @Test
-  public void regulatory_report_feature_enabled_ee_dce() {
-    init();
-    when(editionProvider.get()).thenReturn(Optional.of(ENTERPRISE));
-    assertJson(call()).isSimilarTo("{\"regulatoryReportFeatureEnabled\":true}");
-
-    when(editionProvider.get()).thenReturn(Optional.of(DATACENTER));
-    assertJson(call()).isSimilarTo("{\"regulatoryReportFeatureEnabled\":true}");
-  }
-
-  @Test
-  public void regulatory_report_feature_disabled_ce_de() {
-    init();
-    when(editionProvider.get()).thenReturn(Optional.of(COMMUNITY));
-    assertJson(call()).isSimilarTo("{\"regulatoryReportFeatureEnabled\":false}");
-
-    when(editionProvider.get()).thenReturn(Optional.of(DEVELOPER));
-    assertJson(call()).isSimilarTo("{\"regulatoryReportFeatureEnabled\":false}");
-
-    when(editionProvider.get()).thenReturn(Optional.empty());
-    assertJson(call()).isSimilarTo("{\"regulatoryReportFeatureEnabled\":false}");
-  }
-
   @Test
   public void instance_uses_default_admin_credentials() {
     init();