]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-11028 Turning off developer nominative information
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Mon, 3 Aug 2020 17:58:05 +0000 (12:58 -0500)
committersonartech <sonartech@sonarsource.com>
Mon, 10 Aug 2020 20:06:21 +0000 (20:06 +0000)
server/sonar-web/src/main/js/apps/issues/sidebar/Sidebar.tsx
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-test.tsx
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/Sidebar-test.tsx.snap
server/sonar-webserver-webapi/src/main/java/org/sonar/server/ui/ws/GlobalAction.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/ui/ws/GlobalActionTest.java
sonar-core/src/main/java/org/sonar/core/config/CorePropertyDefinitions.java
sonar-core/src/test/java/org/sonar/core/config/CorePropertyDefinitionsTest.java
sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java

index bac2e2c45956b3f497d0945bbe1354908f488811..e1bc2790ebda96ee988bda5c6aaecd4e93088bc4 100644 (file)
@@ -18,6 +18,8 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import * as React from 'react';
+import { connect } from 'react-redux';
+import { getGlobalSettingValue, Store } from '../../../store/rootReducer';
 import { Facet, Query, ReferencedComponent, ReferencedLanguage, ReferencedRule } from '../utils';
 import AssigneeFacet from './AssigneeFacet';
 import AuthorFacet from './AuthorFacet';
@@ -51,9 +53,10 @@ export interface Props {
   referencedLanguages: T.Dict<ReferencedLanguage>;
   referencedRules: T.Dict<ReferencedRule>;
   referencedUsers: T.Dict<T.UserBase>;
+  disableDeveloperAggregatedInfo: boolean;
 }
 
-export default class Sidebar extends React.PureComponent<Props> {
+export class Sidebar extends React.PureComponent<Props> {
   renderComponentFacets() {
     const { component, facets, loadingFacets, openFacets, query } = this.props;
     if (!component) {
@@ -223,7 +226,7 @@ export default class Sidebar extends React.PureComponent<Props> {
           />
         )}
         {this.renderComponentFacets()}
-        {!this.props.myIssues && (
+        {!this.props.myIssues && !this.props.disableDeveloperAggregatedInfo && (
           <AssigneeFacet
             assigned={query.assigned}
             assignees={query.assignees}
@@ -238,7 +241,7 @@ export default class Sidebar extends React.PureComponent<Props> {
             stats={facets.assignees}
           />
         )}
-        {displayAuthorFacet && (
+        {displayAuthorFacet && !this.props.disableDeveloperAggregatedInfo && (
           <AuthorFacet
             authors={query.authors}
             component={component}
@@ -256,3 +259,15 @@ export default class Sidebar extends React.PureComponent<Props> {
     );
   }
 }
+
+export const mapStateToProps = (state: Store) => {
+  const disableDeveloperAggregatedInfo = getGlobalSettingValue(
+    state,
+    'sonar.developerAggregatedInfo.disabled'
+  );
+  return {
+    disableDeveloperAggregatedInfo: disableDeveloperAggregatedInfo?.value === true.toString()
+  };
+};
+
+export default connect(mapStateToProps)(Sidebar);
index a326273c10fbce7dc2393981d4184a425201a433..2f7b3be7769bf8b2d72c34e5367ddaccd3b14515 100644 (file)
 import { shallow, ShallowWrapper } from 'enzyme';
 import { flatten } from 'lodash';
 import * as React from 'react';
+import { mockComponent } from '../../../../helpers/testMocks';
+import { getGlobalSettingValue } from '../../../../store/rootReducer';
+import { ComponentQualifier } from '../../../../types/component';
 import { Query } from '../../utils';
-import Sidebar, { Props } from '../Sidebar';
+import { mapStateToProps, Sidebar } from '../Sidebar';
 
-jest.mock('../../../../store/rootReducer', () => ({}));
+jest.mock('../../../../store/rootReducer', () => ({ getGlobalSettingValue: jest.fn() }));
 
-const renderSidebar = (props?: Partial<Props>) => {
+it('should render facets for global page', () => {
+  expect(renderSidebar()).toMatchSnapshot();
+});
+
+it('should render facets for project', () => {
+  expect(renderSidebar({ component: mockComponent() })).toMatchSnapshot();
+});
+
+it('should render facets for module', () => {
+  expect(
+    renderSidebar({ component: mockComponent({ qualifier: ComponentQualifier.SubProject }) })
+  ).toMatchSnapshot();
+});
+
+it('should render facets for directory', () => {
+  expect(
+    renderSidebar({ component: mockComponent({ qualifier: ComponentQualifier.Directory }) })
+  ).toMatchSnapshot();
+});
+
+it('should render facets for developer', () => {
+  expect(
+    renderSidebar({ component: mockComponent({ qualifier: ComponentQualifier.Developper }) })
+  ).toMatchSnapshot();
+});
+
+it('should render facets when my issues are selected', () => {
+  expect(renderSidebar({ myIssues: true })).toMatchSnapshot();
+});
+
+it('should not render developer nominative facets when asked not to', () => {
+  expect(renderSidebar({ disableDeveloperAggregatedInfo: true })).toMatchSnapshot();
+});
+
+it('should init the component with the proper store value', () => {
+  mapStateToProps({} as any);
+
+  expect(getGlobalSettingValue).toHaveBeenCalledWith(
+    expect.any(Object),
+    'sonar.developerAggregatedInfo.disabled'
+  );
+});
+
+const renderSidebar = (props?: Partial<Sidebar['props']>) => {
   return flatten(
     mapChildren(
-      shallow(
+      shallow<Sidebar>(
         <Sidebar
           component={undefined}
           facets={{}}
@@ -45,6 +91,7 @@ const renderSidebar = (props?: Partial<Props>) => {
           referencedLanguages={{}}
           referencedRules={{}}
           referencedUsers={{}}
+          disableDeveloperAggregatedInfo={false}
           {...props}
         />
       )
@@ -54,40 +101,9 @@ const renderSidebar = (props?: Partial<Props>) => {
   function mapChildren(wrapper: ShallowWrapper) {
     return wrapper.children().map(node => {
       if (typeof node.type() === 'symbol') {
-        return node.children().map(node => node.name());
+        return node.children().map(n => n.name());
       }
       return node.name();
     });
   }
 };
-
-const component = {
-  breadcrumbs: [],
-  name: 'foo',
-  key: 'foo',
-  organization: 'org'
-};
-
-it('should render facets for global page', () => {
-  expect(renderSidebar()).toMatchSnapshot();
-});
-
-it('should render facets for project', () => {
-  expect(renderSidebar({ component: { ...component, qualifier: 'TRK' } })).toMatchSnapshot();
-});
-
-it('should render facets for module', () => {
-  expect(renderSidebar({ component: { ...component, qualifier: 'BRC' } })).toMatchSnapshot();
-});
-
-it('should render facets for directory', () => {
-  expect(renderSidebar({ component: { ...component, qualifier: 'DIR' } })).toMatchSnapshot();
-});
-
-it('should render facets for developer', () => {
-  expect(renderSidebar({ component: { ...component, qualifier: 'DEV' } })).toMatchSnapshot();
-});
-
-it('should render facets when my issues are selected', () => {
-  expect(renderSidebar({ myIssues: true })).toMatchSnapshot();
-});
index e7274c32bafabfa80ffc6b90ae5c86a5ac18dd6d..09df17ecf9bf344e5841f0d9c5807f3040195742 100644 (file)
@@ -1,5 +1,20 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
+exports[`should not render developer nominative facets when asked not to 1`] = `
+Array [
+  "TypeFacet",
+  "SeverityFacet",
+  "ResolutionFacet",
+  "StatusFacet",
+  "StandardFacet",
+  "InjectIntl(CreationDateFacet)",
+  "Connect(LanguageFacet)",
+  "RuleFacet",
+  "TagFacet",
+  "ProjectFacet",
+]
+`;
+
 exports[`should render facets for developer 1`] = `
 Array [
   "TypeFacet",
index 31ddc1d5c1407d608a260c2ceb581857cfa5f0dc..f9a5a75d15c9f73eff9e99efadc7b49ad3dd3d98 100644 (file)
@@ -49,6 +49,7 @@ import org.sonar.server.ui.VersionFormatter;
 import org.sonar.server.ui.WebAnalyticsLoader;
 import org.sonar.server.user.UserSession;
 
+import static org.sonar.api.CoreProperties.DEVELOPER_AGGREGATED_INFO_DISABLED;
 import static org.sonar.api.CoreProperties.RATING_GRID;
 import static org.sonar.core.config.WebConstants.SONAR_LF_ENABLE_GRAVATAR;
 import static org.sonar.core.config.WebConstants.SONAR_LF_GRAVATAR_SERVER_URL;
@@ -67,7 +68,8 @@ public class GlobalAction implements NavigationWsAction, Startable {
     SONAR_LF_LOGO_WIDTH_PX,
     SONAR_LF_ENABLE_GRAVATAR,
     SONAR_LF_GRAVATAR_SERVER_URL,
-    RATING_GRID);
+    RATING_GRID,
+    DEVELOPER_AGGREGATED_INFO_DISABLED);
 
   private final Map<String, String> systemSettingValuesByKey;
 
index 56cf8231513236a9d75fd5744abfa172e2ca75a3..19ce056cb6963105ee44eeb587213a4c15e77e94 100644 (file)
@@ -51,7 +51,6 @@ import org.sonar.updatecenter.common.Version;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -116,6 +115,7 @@ public class GlobalActionTest {
     settings.setProperty("sonar.lf.enableGravatar", true);
     settings.setProperty("sonar.updatecenter.activate", false);
     settings.setProperty("sonar.technicalDebt.ratingGrid", "0.05,0.1,0.2,0.5");
+    settings.setProperty("sonar.developerAggregatedInfo.disabled", false);
     // This setting should be ignored as it's not needed
     settings.setProperty("sonar.defaultGroup", "sonar-users");
     init();
@@ -128,6 +128,7 @@ public class GlobalActionTest {
       "    \"sonar.lf.enableGravatar\": \"true\"," +
       "    \"sonar.updatecenter.activate\": \"false\"," +
       "    \"sonar.technicalDebt.ratingGrid\": \"0.05,0.1,0.2,0.5\"" +
+      "    \"sonar.developerAggregatedInfo.disabled\": \"false\"" +
       "  }" +
       "}");
   }
@@ -149,6 +150,18 @@ public class GlobalActionTest {
       "}");
   }
 
+  @Test
+  public void return_developer_info_disabled_setting() {
+    init();
+    settings.setProperty("sonar.developerAggregatedInfo.disabled", true);
+
+    assertJson(call()).isSimilarTo("{" +
+      "  \"settings\": {" +
+      "    \"sonar.developerAggregatedInfo.disabled\": \"true\"" +
+      "  }" +
+      "}");
+  }
+
   @Test
   public void return_deprecated_logo_settings() {
     init();
index 295cc2fdaf7754a896027240e4a4da10aa7bed81..d7f9950d0091ba7c928ec07724f0f1753d17b7ba 100644 (file)
@@ -131,6 +131,16 @@ public class CorePropertyDefinitions {
         .build(),
 
       // ISSUES
+      PropertyDefinition.builder(CoreProperties.DEVELOPER_AGGREGATED_INFO_DISABLED)
+        .name("Disable developer aggregated information")
+        .description("Don't show issue facets aggregating information per developer")
+        .category(CoreProperties.CATEGORY_GENERAL)
+        .subCategory(CoreProperties.SUBCATEGORY_ISSUES)
+        .onQualifiers(Qualifiers.PROJECT)
+        .type(BOOLEAN)
+        .defaultValue(Boolean.toString(false))
+        .build(),
+
       PropertyDefinition.builder(CoreProperties.DEFAULT_ISSUE_ASSIGNEE)
         .name("Default Assignee")
         .description("New issues will be assigned to this user each time it is not possible to determine the user who is the author of the issue.")
index e03f5d7868dfb3dc3eae116389143564da15863f..c126792a0af51ddc320f58b9a6f916a3e22e91c1 100644 (file)
@@ -30,7 +30,7 @@ public class CorePropertyDefinitionsTest {
   @Test
   public void all() {
     List<PropertyDefinition> defs = CorePropertyDefinitions.all();
-    assertThat(defs).hasSize(51);
+    assertThat(defs).hasSize(52);
   }
 
   @Test
index b2ba5b2618b7f07cf2c7393d6502f8bec6fce398..3b14bca939e69c1b071b4967f8fcf4cd1ae10a95 100644 (file)
@@ -392,6 +392,11 @@ public interface CoreProperties {
    */
   String DEFAULT_ISSUE_ASSIGNEE = "sonar.issues.defaultAssigneeLogin";
 
+  /**
+   * @since 8.5
+   */
+  String DEVELOPER_AGGREGATED_INFO_DISABLED = "sonar.developerAggregatedInfo.disabled";
+
   /**
    * @since 7.6
    */