]> source.dussan.org Git - sonarqube.git/commitdiff
refactor urls helper
authorStas Vilchik <vilchiks@gmail.com>
Mon, 2 Nov 2015 15:00:33 +0000 (16:00 +0100)
committerStas Vilchik <vilchiks@gmail.com>
Mon, 2 Nov 2015 15:00:33 +0000 (16:00 +0100)
12 files changed:
server/sonar-web/src/main/js/apps/background-tasks/tasks.js
server/sonar-web/src/main/js/apps/overview/domain/bubble-chart.js
server/sonar-web/src/main/js/apps/overview/helpers/drilldown-link.js
server/sonar-web/src/main/js/apps/overview/helpers/issues-link.js
server/sonar-web/src/main/js/apps/overview/issues/assignees.js
server/sonar-web/src/main/js/apps/overview/issues/severities.js
server/sonar-web/src/main/js/apps/overview/issues/tags.js
server/sonar-web/src/main/js/apps/project-permissions/project.js
server/sonar-web/src/main/js/apps/projects/projects.js
server/sonar-web/src/main/js/helpers/Url.js [deleted file]
server/sonar-web/src/main/js/helpers/urls.js [new file with mode: 0644]
server/sonar-web/tests/helpers/urls-test.js [new file with mode: 0644]

index c469637204de056eb639141fa21665cee414defe..2d1b6352768cf9c8b2d99722ee4ed01bb0cea6c8 100644 (file)
@@ -1,6 +1,6 @@
 import moment from 'moment';
 import React from 'react';
-import {getProjectUrl} from '../../helpers/Url';
+import { getComponentUrl } from '../../helpers/urls';
 import QualifierIcon from '../../components/shared/qualifier-icon';
 import PendingIcon from '../../components/shared/pending-icon';
 import {STATUSES} from './constants';
@@ -51,7 +51,7 @@ export default React.createClass({
           <span className="little-spacer-right">
             <QualifierIcon qualifier={task.componentQualifier}/>
           </span>
-          <a href={getProjectUrl(task.componentKey)}>{task.componentName}</a>
+          <a href={getComponentUrl(task.componentKey)}>{task.componentName}</a>
         </td>
     );
   },
index 4a72a92dffc529e0c83e1fcfee555bc420755497..58c65c45ad1bba9cc10452d6a7d394aea1fb3810 100644 (file)
@@ -1,7 +1,7 @@
 import _ from 'underscore';
 import React from 'react';
 import { BubbleChart } from '../../../components/charts/bubble-chart';
-import { getProjectUrl } from '../../../helpers/Url';
+import { getComponentUrl } from '../../../helpers/urls';
 import { getFiles } from '../../../api/components';
 import { formatMeasure } from '../../../helpers/measures';
 
@@ -87,7 +87,7 @@ export class DomainBubbleChart extends React.Component {
         x: getMeasure(component, this.props.xMetric),
         y: getMeasure(component, this.props.yMetric),
         size: this.getSizeMetricsValue(component),
-        link: getProjectUrl(component.key),
+        link: getComponentUrl(component.key),
         tooltip: this.getTooltip(component)
       };
     });
index 338a34bc016272fe116f4c0e1374fd6b5e3d1539..51f18ea39f5b6204ebddfe0cca1fad7c7bfb1527 100644 (file)
@@ -2,6 +2,8 @@ import _ from 'underscore';
 import moment from 'moment';
 import React from 'react';
 import IssuesLink from './issues-link';
+import { getComponentDrilldownUrl } from '../../../helpers/urls';
+
 
 export default React.createClass({
   isIssueMeasure() {
@@ -80,16 +82,7 @@ export default React.createClass({
       return this.renderIssuesLink();
     }
 
-    let params = { id: this.props.component, metric: this.props.metric };
-    if (this.props.period) {
-      params.period = this.props.period;
-    }
-
-    let query = Object.keys(params).map(key => {
-          return `${key}=${encodeURIComponent(params[key])}`;
-        }).join('&'),
-        url = `${baseUrl}/drilldown/measures?${query}`;
-
+    let url = getComponentDrilldownUrl(this.props.component, this.props.metric, this.props.period);
     return <a href={url}>{this.props.children}</a>;
   }
 });
index f133139567125ebd0e8c32f0c87aaf51b048fe92..065961496b4e2b3c1db496572f4d512b06ce07be 100644 (file)
@@ -1,11 +1,10 @@
 import React from 'react';
+import { getComponentIssuesUrl } from '../../../helpers/urls';
+
 
 export default React.createClass({
   render() {
-    let params = Object.keys(this.props.params).map((key) => {
-          return `${key}=${encodeURIComponent(this.props.params[key])}`;
-        }).join('|'),
-        url = `${window.baseUrl}/component_issues/index?id=${encodeURIComponent(this.props.component)}#${params}`;
+    let url = getComponentIssuesUrl(this.props.component, this.props.params);
     return <a href={url}>{this.props.children}</a>;
   }
 });
index 87c55e1de699ce86698da5f62a276ec7008a8d2c..b13bc21fd0ca0e27f4f3eab0043258f30e17a81d 100644 (file)
@@ -1,14 +1,14 @@
 import React from 'react';
 import Assignee from '../../../components/shared/assignee-helper';
 import { DomainHeader } from '../domain/header';
-import { componentIssuesUrl } from '../../../helpers/Url';
+import { getComponentIssuesUrl } from '../../../helpers/urls';
 import { formatMeasure } from '../../../helpers/measures';
 
 
 export default class extends React.Component {
   render () {
     let rows = this.props.assignees.map(s => {
-      let href = componentIssuesUrl(this.props.component.key, { statuses: 'OPEN,REOPENED', assignees: s.val });
+      let href = getComponentIssuesUrl(this.props.component.key, { statuses: 'OPEN,REOPENED', assignees: s.val });
       return <tr key={s.val}>
         <td>
           <Assignee user={s.user}/>
index efd0e8e31845d63eb1e4e62441cdca444e25e4a6..26008e4648f65de01c1cf2e78e7ac7f99b16a35d 100644 (file)
@@ -2,7 +2,7 @@ import _ from 'underscore';
 import React from 'react';
 import SeverityHelper from '../../../components/shared/severity-helper';
 import { DomainHeader } from '../domain/header';
-import { componentIssuesUrl } from '../../../helpers/Url';
+import { getComponentIssuesUrl } from '../../../helpers/urls';
 import { formatMeasure } from '../../../helpers/measures';
 
 
@@ -13,7 +13,7 @@ export default class extends React.Component {
 
   render () {
     let rows = this.sortedSeverities().map(s => {
-      let href = componentIssuesUrl(this.props.component.key, { resolved: 'false', severities: s.val });
+      let href = getComponentIssuesUrl(this.props.component.key, { resolved: 'false', severities: s.val });
       return <tr key={s.val}>
         <td>
           <SeverityHelper severity={s.val}/>
index 4d86824d25f0f8c80797724d466cd14596383045..6c91a4539b1d6e8d058540d9f927efa4c2d0561b 100644 (file)
@@ -1,14 +1,14 @@
 import React from 'react';
 import { DomainHeader } from '../domain/header';
 import { WordCloud } from '../../../components/charts/word-cloud';
-import { componentIssuesUrl } from '../../../helpers/Url';
+import { getComponentIssuesUrl } from '../../../helpers/urls';
 import { formatMeasure } from '../../../helpers/measures';
 
 
 export default class extends React.Component {
   renderWordCloud () {
     let tags = this.props.tags.map(tag => {
-      let link = componentIssuesUrl(this.props.component.key, { resolved: 'false', tags: tag.val });
+      let link = getComponentIssuesUrl(this.props.component.key, { resolved: 'false', tags: tag.val });
       let tooltip = `Issues: ${formatMeasure(tag.count, 'SHORT_INT')}`;
       return { text: tag.val, size: tag.count, link, tooltip };
     });
index ce1b9dae58c57b33d1f3a19ae788577a24d8b91b..f7de774d8970f742d7e7fc7ae8c73b77e33e647a 100644 (file)
@@ -2,7 +2,7 @@ import React from 'react';
 import UsersView from './users-view';
 import GroupsView from './groups-view';
 import ApplyTemplateView from './apply-template-view';
-import {getProjectUrl} from '../../helpers/Url';
+import { getComponentUrl } from '../../helpers/urls';
 import QualifierIcon from '../../components/shared/qualifier-icon';
 
 export default React.createClass({
@@ -74,7 +74,7 @@ export default React.createClass({
             <span className="little-spacer-right">
               <QualifierIcon qualifier={this.props.project.qualifier}/>
             </span>
-            <a href={getProjectUrl(this.props.project.key)}>{this.props.project.name}</a>
+            <a href={getComponentUrl(this.props.project.key)}>{this.props.project.name}</a>
           </td>
           {permissions}
           <td className="thin nowrap text-right">
index 6aa42f53c0b58e190d462d91665139c97f9632a5..1f3babcd067cf5427edf0d1406a77357649dbaf6 100644 (file)
@@ -1,5 +1,5 @@
 import React from 'react';
-import {getProjectUrl} from '../../helpers/Url';
+import { getComponentUrl } from '../../helpers/urls';
 import Checkbox from '../../components/shared/checkbox';
 import QualifierIcon from '../../components/shared/qualifier-icon';
 
@@ -33,7 +33,7 @@ export default React.createClass({
             <QualifierIcon qualifier={project.qualifier}/>
           </td>
           <td className="nowrap">
-            <a href={getProjectUrl(project.key)}>{project.name}</a>
+            <a href={getComponentUrl(project.key)}>{project.name}</a>
           </td>
           <td className="nowrap">
             <span className="note">{project.key}</span>
diff --git a/server/sonar-web/src/main/js/helpers/Url.js b/server/sonar-web/src/main/js/helpers/Url.js
deleted file mode 100644 (file)
index f369bb7..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-export function getProjectUrl (project) {
-  if (typeof project !== 'string') {
-    throw new TypeError('Project ID or KEY should be passed');
-  }
-  return `${window.baseUrl}/dashboard?id=${encodeURIComponent(project)}`;
-}
-
-export function componentIssuesUrl (componentKey, query) {
-  let serializedQuery = Object.keys(query).map(criterion => {
-    return `${encodeURIComponent(criterion)}=${encodeURIComponent(query[criterion])}`;
-  }).join('|');
-  return window.baseUrl + '/component_issues?id=' + encodeURIComponent(componentKey) + '#' + serializedQuery;
-}
diff --git a/server/sonar-web/src/main/js/helpers/urls.js b/server/sonar-web/src/main/js/helpers/urls.js
new file mode 100644 (file)
index 0000000..4af420e
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * Generate URL for a component's home page
+ * @param {string} componentKey
+ * @returns {string}
+ */
+export function getComponentUrl (componentKey) {
+  return window.baseUrl + '/dashboard?id=' + encodeURIComponent(componentKey);
+}
+
+
+/**
+ * Generate URL for a component's issues page
+ * @param {string} componentKey
+ * @param {object} query
+ * @returns {string}
+ */
+export function getComponentIssuesUrl (componentKey, query) {
+  let serializedQuery = Object.keys(query).map(criterion => {
+    return `${encodeURIComponent(criterion)}=${encodeURIComponent(query[criterion])}`;
+  }).join('|');
+  return window.baseUrl + '/component_issues?id=' + encodeURIComponent(componentKey) + '#' + serializedQuery;
+}
+
+
+/**
+ * Generate URL for a component's drilldown page
+ * @param {string} componentKey
+ * @param {string} metric
+ * @param {string|number} [period]
+ * @returns {string}
+ */
+export function getComponentDrilldownUrl (componentKey, metric, period) {
+  let url = window.baseUrl + '/drilldown/measures?id=' + encodeURIComponent(componentKey) +
+      '&metric=' + encodeURIComponent(metric);
+  if (period) {
+    url += '&period=' + period;
+  }
+  return url;
+}
diff --git a/server/sonar-web/tests/helpers/urls-test.js b/server/sonar-web/tests/helpers/urls-test.js
new file mode 100644 (file)
index 0000000..da02b32
--- /dev/null
@@ -0,0 +1,89 @@
+import { expect } from 'chai';
+
+import { getComponentUrl, getComponentIssuesUrl, getComponentDrilldownUrl } from '../../src/main/js/helpers/urls';
+
+
+const SIMPLE_COMPONENT_KEY = 'sonarqube';
+const COMPLEX_COMPONENT_KEY = 'org.sonarsource.sonarqube:sonarqube';
+const COMPLEX_COMPONENT_KEY_ENCODED = encodeURIComponent(COMPLEX_COMPONENT_KEY);
+const METRIC = 'coverage';
+const PERIOD = '3';
+
+
+describe('URLs', function () {
+  var oldBaseUrl;
+
+  beforeEach(function () {
+    oldBaseUrl = window.baseUrl;
+  });
+
+  afterEach(function () {
+    window.baseUrl = oldBaseUrl;
+  });
+
+  describe('#getComponentUrl', function () {
+    it('should return component url', function () {
+      expect(getComponentUrl(SIMPLE_COMPONENT_KEY)).to.equal('/dashboard?id=' + SIMPLE_COMPONENT_KEY);
+    });
+
+    it('should encode component key', function () {
+      expect(getComponentUrl(COMPLEX_COMPONENT_KEY)).to.equal('/dashboard?id=' + COMPLEX_COMPONENT_KEY_ENCODED);
+    });
+
+    it('should take baseUrl into account', function () {
+      window.baseUrl = '/context';
+      expect(getComponentUrl(COMPLEX_COMPONENT_KEY)).to.equal('/context/dashboard?id=' + COMPLEX_COMPONENT_KEY_ENCODED);
+    });
+  });
+
+  describe('#getComponentIssuesUrl', function () {
+    it('should work without parameters', function () {
+      expect(getComponentIssuesUrl(SIMPLE_COMPONENT_KEY, {})).to.equal(
+          '/component_issues?id=' + SIMPLE_COMPONENT_KEY + '#');
+    });
+
+    it('should encode component key', function () {
+      expect(getComponentIssuesUrl(COMPLEX_COMPONENT_KEY, {})).to.equal(
+          '/component_issues?id=' + COMPLEX_COMPONENT_KEY_ENCODED + '#');
+    });
+
+    it('should work with parameters', function () {
+      expect(getComponentIssuesUrl(SIMPLE_COMPONENT_KEY, { resolved: 'false' })).to.equal(
+          '/component_issues?id=' + SIMPLE_COMPONENT_KEY + '#resolved=false');
+    });
+
+    it('should encode parameters', function () {
+      expect(getComponentIssuesUrl(SIMPLE_COMPONENT_KEY, { componentUuids: COMPLEX_COMPONENT_KEY })).to.equal(
+          '/component_issues?id=' + SIMPLE_COMPONENT_KEY + '#componentUuids=' + COMPLEX_COMPONENT_KEY_ENCODED);
+    });
+
+    it('should take baseUrl into account', function () {
+      window.baseUrl = '/context';
+      expect(getComponentIssuesUrl(SIMPLE_COMPONENT_KEY, {})).to.equal(
+          '/context/component_issues?id=' + SIMPLE_COMPONENT_KEY + '#');
+    });
+  });
+
+  describe('#getComponentDrilldownUrl', function () {
+    it('should return component drilldown url', function () {
+      expect(getComponentDrilldownUrl(SIMPLE_COMPONENT_KEY, METRIC)).to.equal(
+          '/drilldown/measures?id=' + SIMPLE_COMPONENT_KEY + '&metric=' + METRIC);
+    });
+
+    it('should encode component key', function () {
+      expect(getComponentDrilldownUrl(COMPLEX_COMPONENT_KEY, METRIC)).to.equal(
+          '/drilldown/measures?id=' + COMPLEX_COMPONENT_KEY_ENCODED + '&metric=' + METRIC);
+    });
+
+    it('should work with period', function () {
+      expect(getComponentDrilldownUrl(SIMPLE_COMPONENT_KEY, METRIC, PERIOD)).to.equal(
+          '/drilldown/measures?id=' + SIMPLE_COMPONENT_KEY + '&metric=' + METRIC + '&period=' + PERIOD);
+    });
+
+    it('should take baseUrl into account', function () {
+      window.baseUrl = '/context';
+      expect(getComponentDrilldownUrl(SIMPLE_COMPONENT_KEY, METRIC)).to.equal(
+          '/context/drilldown/measures?id=' + SIMPLE_COMPONENT_KEY + '&metric=' + METRIC);
+    });
+  });
+});