]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-18343 Purpose of link is not clear in context
authorstanislavh <stanislav.honcharov@sonarsource.com>
Tue, 7 Feb 2023 09:32:49 +0000 (10:32 +0100)
committersonartech <sonartech@sonarsource.com>
Thu, 9 Feb 2023 20:03:34 +0000 (20:03 +0000)
server/sonar-web/src/main/js/api/mocks/QualityProfilesServiceMock.ts
server/sonar-web/src/main/js/apps/quality-profiles/__tests__/QualityProfilesApp-it.tsx
server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionRules.tsx

index 35dbe0852f0b0ffad0ca58c6bede5cfcfb0fd543..b26903edf06b225d5729c799e53a5608a5411062 100644 (file)
@@ -48,6 +48,12 @@ export default class QualityProfilesServiceMock {
   };
 
   comparisonResult: CompareResponse = mockCompareResult();
+  searchRulesResponse: SearchRulesResponse = {
+    p: 0,
+    ps: 500,
+    total: 0,
+    rules: [],
+  };
 
   constructor() {
     this.resetQualityProfile();
@@ -99,6 +105,15 @@ export default class QualityProfilesServiceMock {
     this.comparisonResult = mockCompareResult();
   }
 
+  resetSearchRulesResponse() {
+    this.searchRulesResponse = {
+      p: 0,
+      ps: 500,
+      total: 0,
+      rules: [],
+    };
+  }
+
   handleGetImporters = () => {
     return this.reply([]);
   };
@@ -207,12 +222,7 @@ export default class QualityProfilesServiceMock {
   };
 
   handleSearchRules = (): Promise<SearchRulesResponse> => {
-    return this.reply({
-      p: 0,
-      ps: 500,
-      total: 0,
-      rules: [],
-    });
+    return this.reply(this.searchRulesResponse);
   };
 
   handleSearchQualityProfiles = (
@@ -277,10 +287,18 @@ export default class QualityProfilesServiceMock {
     this.isAdmin = true;
   }
 
+  setRulesSearchResponse(overrides: Partial<SearchRulesResponse>) {
+    this.searchRulesResponse = {
+      ...this.searchRulesResponse,
+      ...overrides,
+    };
+  }
+
   reset() {
     this.isAdmin = false;
     this.resetQualityProfile();
     this.resetComparisonResult();
+    this.resetSearchRulesResponse();
   }
 
   reply<T>(response: T): Promise<T> {
index b63ffbf6ff65b579df44a7acbd990a72aef0ce85..7d5413dbbff780192022378e3928477532fd03ad 100644 (file)
@@ -22,6 +22,7 @@ import userEvent from '@testing-library/user-event';
 import selectEvent from 'react-select-event';
 import { byRole } from 'testing-library-selector';
 import QualityProfilesServiceMock from '../../../api/mocks/QualityProfilesServiceMock';
+import { mockRule } from '../../../helpers/testMocks';
 import { renderAppRoutes } from '../../../helpers/testReactTestingUtils';
 import routes from '../routes';
 
@@ -87,6 +88,8 @@ const ui = {
     byRole('heading', {
       name: `quality_profiles.x_rules_have_different_configuration.${rulesQuantity}`,
     }),
+  newRuleLink: byRole('link', { name: 'Recently Added Rule' }),
+  seeAllNewRulesLink: byRole('link', { name: 'see_all 20 quality_profiles.latest_new_rules' }),
 };
 
 it('should list Quality Profiles and filter by language', async () => {
@@ -110,6 +113,18 @@ it('should list Quality Profiles and filter by language', async () => {
   expect(ui.createButton.get(ui.popup.get())).toBeEnabled();
 });
 
+it('should list recently added rules', async () => {
+  serviceMock.setAdmin();
+  serviceMock.setRulesSearchResponse({
+    rules: [mockRule({ name: 'Recently Added Rule' })],
+    total: 20,
+  });
+
+  renderQualityProfiles();
+  expect(await ui.newRuleLink.find()).toBeInTheDocument();
+  expect(ui.seeAllNewRulesLink.get()).toBeInTheDocument();
+});
+
 it('should be able to extend Quality Profile', async () => {
   // From the list page
   const user = userEvent.setup();
index 48eea458cea3ccf410f1fc5da8c16ded9ba59278..82edf68b9391c817a45e34a00184740c14771198 100644 (file)
@@ -91,19 +91,27 @@ export default class EvolutionRules extends React.PureComponent<{}, State> {
   }
 
   render() {
-    if (!this.state.latestRulesTotal || !this.state.latestRules) {
+    const { latestRulesTotal, latestRules } = this.state;
+
+    if (!latestRulesTotal || !latestRules) {
       return null;
     }
 
+    const newRulesTitle = translate('quality_profiles.latest_new_rules');
     const newRulesUrl = getRulesUrl({ available_since: this.periodStartDate });
+    const seeAllRulesText = `${translate('see_all')} ${formatMeasure(
+      latestRulesTotal,
+      'SHORT_INT',
+      null
+    )}`;
 
     return (
       <div className="boxed-group boxed-group-inner quality-profiles-evolution-rules">
         <div className="clearfix">
-          <strong className="pull-left">{translate('quality_profiles.latest_new_rules')}</strong>
+          <strong className="pull-left">{newRulesTitle}</strong>
         </div>
         <ul>
-          {this.state.latestRules.map((rule) => (
+          {latestRules.map((rule) => (
             <li className="spacer-top" key={rule.key}>
               <div className="text-ellipsis">
                 <Link className="link-no-underline" to={getRulesUrl({ rule_key: rule.key })}>
@@ -126,10 +134,14 @@ export default class EvolutionRules extends React.PureComponent<{}, State> {
             </li>
           ))}
         </ul>
-        {this.state.latestRulesTotal > RULES_LIMIT && (
+        {latestRulesTotal > RULES_LIMIT && (
           <div className="spacer-top">
-            <Link className="small" to={newRulesUrl}>
-              {translate('see_all')} {formatMeasure(this.state.latestRulesTotal, 'SHORT_INT', null)}
+            <Link
+              className="small"
+              to={newRulesUrl}
+              aria-label={`${seeAllRulesText} ${newRulesTitle}`}
+            >
+              {seeAllRulesText}
             </Link>
           </div>
         )}