]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10074 Use new QP actions 'delete' and 'associateProjects'
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>
Fri, 1 Dec 2017 14:44:27 +0000 (15:44 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 4 Dec 2017 15:02:52 +0000 (16:02 +0100)
server/sonar-qa-util/src/main/java/org/sonarqube/qa/util/pageobjects/QualityProfilePage.java
server/sonar-web/src/main/js/api/quality-profiles.ts
server/sonar-web/src/main/js/apps/quality-profiles/components/BuiltInQualityProfileBadge.tsx
server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileActions.tsx
server/sonar-web/src/main/js/apps/quality-profiles/components/__tests__/ProfileActions-test.tsx
server/sonar-web/src/main/js/apps/quality-profiles/components/__tests__/__snapshots__/ProfileActions-test.tsx.snap
server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileProjects.tsx
tests/src/test/java/org/sonarqube/tests/qualityProfile/OrganizationQualityProfilesUiTest.java

index 88b009687b08d6880dbd6f3c7ce3263ddce4a3a6..0541b1bd794c57325573146b11ddd480a9f90aab 100644 (file)
@@ -48,7 +48,19 @@ public class QualityProfilePage {
 
   public QualityProfilePage shouldAllowToChangeProjects() {
     Selenide.$(".js-change-projects").shouldBe(Condition.visible).click();
-    Selenide.$("#profile-projects .select-list-list").shouldBe(Condition.visible);
+    Selenide.$("#profile-projects .select-list-list-container").shouldBe(Condition.visible);
+    return this;
+  }
+
+  public QualityProfilePage shouldNotAllowToChangeProjects() {
+    Selenide.$(".js-change-projects").shouldNot(Condition.exist);
+    return this;
+  }
+
+  public QualityProfilePage shouldNotAllowToEdit() {
+    Selenide.$("button.dropdown-toggle").should(Condition.exist).click();
+    Selenide.$("#quality-profile-rename").shouldNot(Condition.exist);
+    Selenide.$("#quality-profile-activate-more-rules").shouldNot(Condition.exist);
     return this;
   }
 }
index 77bc186880951790211c0e50205c528298d020d5..5488682fa16e208b46dbd414f48855d4ddf8858d 100644 (file)
@@ -30,7 +30,9 @@ import { Paging } from '../app/types';
 import throwGlobalError from '../app/utils/throwGlobalError';
 
 export interface ProfileActions {
+  associateProjects?: boolean;
   copy?: boolean;
+  delete?: boolean;
   edit?: boolean;
   setAsDefault?: boolean;
 }
@@ -104,7 +106,7 @@ export function restoreQualityProfile(data: RequestData): Promise<any> {
 }
 
 export function getProfileProjects(data: RequestData): Promise<any> {
-  return getJSON('/api/qualityprofiles/projects', data);
+  return getJSON('/api/qualityprofiles/projects', data).catch(throwGlobalError);
 }
 
 export function getProfileInheritance(profileKey: string): Promise<any> {
index f7e7d5f26795f96b127455d1e477be330876e342..9cda74cbfe1dbfeebf2b5afed7d665585badc613 100644 (file)
@@ -41,5 +41,11 @@ export default function BuiltInQualityProfileBadge({ className, tooltip = true }
     </span>
   );
 
-  return tooltip ? <Tooltip overlay={overlay}>{badge}</Tooltip> : badge;
+  return tooltip ? (
+    <Tooltip overlay={overlay} placement="right">
+      {badge}
+    </Tooltip>
+  ) : (
+    badge
+  );
 }
index 0a2aff5cffbe8f5f17057d5849138b8338f3182f..0ed58dbb34c0e4638b27908253c0b09ba5a0ae84 100644 (file)
@@ -137,15 +137,10 @@ export default class ProfileActions extends React.PureComponent<Props, State> {
       this.props.organization
     );
 
-    const canActivateRules = actions.edit && !profile.isBuiltIn;
-    const canRename = actions.edit && !profile.isBuiltIn;
-    const canSetAsDefault = actions.setAsDefault && !profile.isDefault;
-    const canDelete = actions.edit && !profile.isDefault && !profile.isBuiltIn;
-
     return (
       <ActionsDropdown className={this.props.className}>
-        {canActivateRules && (
-          <ActionsDropdownItem to={activateMoreUrl}>
+        {actions.edit && (
+          <ActionsDropdownItem to={activateMoreUrl} id="quality-profile-activate-more-rules">
             {translate('quality_profiles.activate_more_rules')}
           </ActionsDropdownItem>
         )}
@@ -171,13 +166,13 @@ export default class ProfileActions extends React.PureComponent<Props, State> {
           </ActionsDropdownItem>
         )}
 
-        {canRename && (
+        {actions.edit && (
           <ActionsDropdownItem id="quality-profile-rename" onClick={this.handleRenameClick}>
             {translate('rename')}
           </ActionsDropdownItem>
         )}
 
-        {canSetAsDefault && (
+        {actions.setAsDefault && (
           <ActionsDropdownItem
             id="quality-profile-set-as-default"
             onClick={this.handleSetDefaultClick}>
@@ -185,9 +180,9 @@ export default class ProfileActions extends React.PureComponent<Props, State> {
           </ActionsDropdownItem>
         )}
 
-        {canDelete && <ActionsDropdownDivider />}
+        {actions.delete && <ActionsDropdownDivider />}
 
-        {canDelete && (
+        {actions.delete && (
           <ActionsDropdownItem
             destructive={true}
             id="quality-profile-delete"
index f54dde5ed08da3fb79de11034058eeb9603f19cb..ee33feb4d5182a770c25c83e783178b08fbd999c 100644 (file)
@@ -50,7 +50,7 @@ it('renders with no permissions', () => {
   ).toMatchSnapshot();
 });
 
-it('renders with permission to edit', () => {
+it('renders with permission to edit only', () => {
   expect(
     shallow(
       <ProfileActions
@@ -69,7 +69,16 @@ it('renders with all permissions', () => {
       <ProfileActions
         onRequestFail={jest.fn()}
         organization="org"
-        profile={{ ...PROFILE, actions: { copy: true, edit: true, setAsDefault: true } }}
+        profile={{
+          ...PROFILE,
+          actions: {
+            copy: true,
+            edit: true,
+            delete: true,
+            setAsDefault: true,
+            associateProjects: true
+          }
+        }}
         updateProfiles={jest.fn()}
       />
     )
index ba760e5cb626d0e058c749f823a3c85c419249e6..7e53929904b5c8b388555a7ee73dccfe5af4c5b4 100644 (file)
@@ -3,6 +3,7 @@
 exports[`renders with all permissions 1`] = `
 <ActionsDropdown>
   <ActionsDropdownItem
+    id="quality-profile-activate-more-rules"
     to="/organizations/org/rules#qprofile=foo|activation=false"
   >
     quality_profiles.activate_more_rules
@@ -83,9 +84,10 @@ exports[`renders with no permissions 1`] = `
 </ActionsDropdown>
 `;
 
-exports[`renders with permission to edit 1`] = `
+exports[`renders with permission to edit only 1`] = `
 <ActionsDropdown>
   <ActionsDropdownItem
+    id="quality-profile-activate-more-rules"
     to="/organizations/org/rules#qprofile=foo|activation=false"
   >
     quality_profiles.activate_more_rules
@@ -117,13 +119,5 @@ exports[`renders with permission to edit 1`] = `
   >
     rename
   </ActionsDropdownItem>
-  <ActionsDropdownDivider />
-  <ActionsDropdownItem
-    destructive={true}
-    id="quality-profile-delete"
-    onClick={[Function]}
-  >
-    delete
-  </ActionsDropdownItem>
 </ActionsDropdown>
 `;
index 9b1acd46c8e1d9cdef7085b62fd10e259cbd5891..66476d8c966e00727aaa4c7d6ab722b903b9fb9d 100644 (file)
@@ -69,15 +69,18 @@ export default class ProfileProjects extends React.PureComponent<Props, State> {
     }
 
     const data = { key: this.props.profile.key };
-    getProfileProjects(data).then((r: any) => {
-      if (this.mounted) {
-        this.setState({
-          projects: r.results,
-          more: r.more,
-          loading: false
-        });
-      }
-    });
+    getProfileProjects(data).then(
+      (r: any) => {
+        if (this.mounted) {
+          this.setState({
+            projects: r.results,
+            more: r.more,
+            loading: false
+          });
+        }
+      },
+      () => {}
+    );
   }
 
   handleChangeClick = (event: React.SyntheticEvent<HTMLElement>) => {
@@ -91,6 +94,10 @@ export default class ProfileProjects extends React.PureComponent<Props, State> {
   };
 
   renderDefault() {
+    if (this.state.loading) {
+      return <i className="spinner" />;
+    }
+
     return (
       <div>
         <span className="badge spacer-right">{translate('default')}</span>
@@ -100,6 +107,10 @@ export default class ProfileProjects extends React.PureComponent<Props, State> {
   }
 
   renderProjects() {
+    if (this.state.loading) {
+      return <i className="spinner" />;
+    }
+
     const { projects } = this.state;
 
     if (projects == null) {
@@ -130,8 +141,7 @@ export default class ProfileProjects extends React.PureComponent<Props, State> {
     return (
       <div className="boxed-group quality-profile-projects">
         {profile.actions &&
-          profile.actions.edit &&
-          !profile.isDefault && (
+          profile.actions.associateProjects && (
             <div className="boxed-group-actions">
               <button className="js-change-projects" onClick={this.handleChangeClick}>
                 {translate('quality_profiles.change_projects')}
@@ -144,13 +154,7 @@ export default class ProfileProjects extends React.PureComponent<Props, State> {
         </header>
 
         <div className="boxed-group-inner">
-          {this.state.loading ? (
-            <i className="spinner" />
-          ) : profile.isDefault ? (
-            this.renderDefault()
-          ) : (
-            this.renderProjects()
-          )}
+          {profile.isDefault ? this.renderDefault() : this.renderProjects()}
         </div>
 
         {this.state.formOpen && (
index 48470073a6ba95c50097e6859abe818934032e67..d9445e5896d76611944c70e99b3e643aef54c680 100644 (file)
@@ -117,6 +117,17 @@ public class OrganizationQualityProfilesUiTest {
     $(".js-profile-comparison .Select-control").click();
   }
 
+  @Test
+  public void testBuiltIn() {
+    Navigation nav = tester.openBrowser().logIn().submitCredentials(user.getLogin());
+    nav.openQualityProfile("xoo", "Sonar way", "test-org")
+      .shouldNotAllowToEdit()
+      .shouldAllowToChangeProjects();
+    nav.openQualityProfile("xoo", "Basic", "test-org")
+      .shouldNotAllowToEdit()
+      .shouldNotAllowToChangeProjects();
+  }
+
   @Test
   public void testCreation() {
     Selenese.runSelenese(orchestrator, "/organization/OrganizationQualityProfilesUiTest/should_create.html");