]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-12392 Fix Issue filtering using Directory facet
authorWouter Admiraal <wouter.admiraal@sonarsource.com>
Fri, 9 Aug 2019 06:36:54 +0000 (08:36 +0200)
committerSonarTech <sonartech@sonarsource.com>
Tue, 27 Aug 2019 18:21:04 +0000 (20:21 +0200)
server/sonar-web/src/main/js/api/components.ts
server/sonar-web/src/main/js/apps/issues/sidebar/DirectoryFacet.tsx
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/DirectoryFacet-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/DirectoryFacet-test.tsx.snap [new file with mode: 0644]

index ea2f2381150ea40b918e18aff267b34d313a08fc..8b26dacc1bb1ebd5bba819421cbfdeab8774d9a9 100644 (file)
@@ -160,6 +160,10 @@ export function getFiles(data: GetTreeParams) {
   return getTree<TreeComponentWithPath>({ ...data, qualifiers: 'FIL' });
 }
 
+export function getDirectories(data: GetTreeParams) {
+  return getTree<TreeComponentWithPath>({ ...data, qualifiers: 'DIR' });
+}
+
 export function getComponentData(data: { component: string } & T.BranchParameters): Promise<any> {
   return getJSON('/api/components/show', data);
 }
index 3eb7246ae1fb211036b85168de406952d8c1bb99..bc092c083adc8585e5bcce487c4ac8eeeac03405 100644 (file)
@@ -23,48 +23,50 @@ import QualifierIcon from 'sonar-ui-common/components/icons/QualifierIcon';
 import { translate } from 'sonar-ui-common/helpers/l10n';
 import { collapsePath } from 'sonar-ui-common/helpers/path';
 import { highlightTerm } from 'sonar-ui-common/helpers/search';
-import { getTree, TreeComponent } from '../../../api/components';
+import { getDirectories, TreeComponentWithPath } from '../../../api/components';
 import ListStyleFacet from '../../../components/facet/ListStyleFacet';
 import { Facet, Query } from '../utils';
 
 interface Props {
   componentKey: string;
-  fetching: boolean;
   directories: string[];
+  fetching: boolean;
   loadSearchResultCount: (property: string, changes: Partial<Query>) => Promise<Facet>;
   onChange: (changes: Partial<Query>) => void;
   onToggle: (property: string) => void;
   open: boolean;
   query: Query;
-  stats: T.Dict<number> | undefined;
+  stats: Facet | undefined;
 }
 
 export default class DirectoryFacet extends React.PureComponent<Props> {
-  getFacetItemText = (directory: string) => {
-    return collapsePath(directory, 15);
+  getFacetItemText = (path: string) => {
+    return collapsePath(path, 15);
   };
 
-  getSearchResultKey = (directory: TreeComponent) => {
-    return directory.name;
+  getSearchResultKey = (directory: TreeComponentWithPath) => {
+    return directory.path;
   };
 
-  getSearchResultText = (directory: TreeComponent) => {
+  getSearchResultText = (directory: TreeComponentWithPath) => {
     return directory.name;
   };
 
   handleSearch = (query: string, page: number) => {
-    return getTree({
+    return getDirectories({
       component: this.props.componentKey,
       q: query,
-      qualifiers: 'DIR',
       p: page,
       ps: 30
-    }).then(({ components, paging }) => ({ paging, results: components }));
+    }).then(({ components, paging }) => ({
+      paging,
+      results: components.filter(dir => dir.path !== undefined)
+    }));
   };
 
-  loadSearchResultCount = (directories: TreeComponent[]) => {
+  loadSearchResultCount = (directories: TreeComponentWithPath[]) => {
     return this.props.loadSearchResultCount('directories', {
-      directories: directories.map(directory => directory.name)
+      directories: directories.map(directory => directory.path)
     });
   };
 
@@ -75,17 +77,17 @@ export default class DirectoryFacet extends React.PureComponent<Props> {
     </>
   );
 
-  renderFacetItem = (directory: string) => {
-    return this.renderDirectory(collapsePath(directory, 15));
+  renderFacetItem = (path: string) => {
+    return this.renderDirectory(collapsePath(path, 15));
   };
 
-  renderSearchResult = (directory: TreeComponent, term: string) => {
-    return this.renderDirectory(highlightTerm(collapsePath(directory.name), term));
+  renderSearchResult = (directory: TreeComponentWithPath, term: string) => {
+    return this.renderDirectory(highlightTerm(collapsePath(directory.path, 15), term));
   };
 
   render() {
     return (
-      <ListStyleFacet<TreeComponent>
+      <ListStyleFacet<TreeComponentWithPath>
         facetHeader={translate('issues.facet.directories')}
         fetching={this.props.fetching}
         getFacetItemText={this.getFacetItemText}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/DirectoryFacet-test.tsx b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/DirectoryFacet-test.tsx
new file mode 100644 (file)
index 0000000..0b9f9ba
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import { TreeComponentWithPath } from '../../../../api/components';
+import { Query } from '../../utils';
+import DirectoryFacet from '../DirectoryFacet';
+
+it('should render correctly', () => {
+  const wrapper = shallowRender();
+  const instance = wrapper.instance();
+  expect(wrapper).toMatchSnapshot();
+  expect(
+    instance.renderSearchResult({ path: 'foo/bar' } as TreeComponentWithPath, 'foo')
+  ).toMatchSnapshot();
+  expect(instance.renderFacetItem('foo/bar')).toMatchSnapshot();
+});
+
+describe("ListStyleFacet's callback props", () => {
+  const wrapper = shallowRender();
+  const instance = wrapper.instance();
+
+  test('#getSearchResultText()', () => {
+    expect(instance.getSearchResultText({ name: 'bar' } as TreeComponentWithPath)).toBe('bar');
+  });
+
+  test('#getSearchResultKey()', () => {
+    expect(instance.getSearchResultKey({ path: 'foo/bar' } as TreeComponentWithPath)).toBe(
+      'foo/bar'
+    );
+  });
+
+  test('#getFacetItemText()', () => {
+    expect(instance.getFacetItemText('foo/bar')).toBe('foo/bar');
+  });
+});
+
+function shallowRender(props: Partial<DirectoryFacet['props']> = {}) {
+  return shallow<DirectoryFacet>(
+    <DirectoryFacet
+      componentKey="foo"
+      directories={['foo/', 'bar/baz/']}
+      fetching={false}
+      loadSearchResultCount={jest.fn()}
+      onChange={jest.fn()}
+      onToggle={jest.fn()}
+      open={false}
+      query={{} as Query}
+      stats={undefined}
+      {...props}
+    />
+  );
+}
diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/DirectoryFacet-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/__snapshots__/DirectoryFacet-test.tsx.snap
new file mode 100644 (file)
index 0000000..ce08e6f
--- /dev/null
@@ -0,0 +1,55 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<ListStyleFacet
+  facetHeader="issues.facet.directories"
+  fetching={false}
+  getFacetItemText={[Function]}
+  getSearchResultKey={[Function]}
+  getSearchResultText={[Function]}
+  loadSearchResultCount={[Function]}
+  maxInitialItems={15}
+  maxItems={100}
+  minSearchLength={3}
+  onChange={[MockFunction]}
+  onSearch={[Function]}
+  onToggle={[MockFunction]}
+  open={false}
+  property="directories"
+  query={Object {}}
+  renderFacetItem={[Function]}
+  renderSearchResult={[Function]}
+  searchPlaceholder="search.search_for_directories"
+  values={
+    Array [
+      "foo/",
+      "bar/baz/",
+    ]
+  }
+/>
+`;
+
+exports[`should render correctly 2`] = `
+<React.Fragment>
+  <QualifierIcon
+    className="little-spacer-right"
+    qualifier="DIR"
+  />
+  <React.Fragment>
+    <mark>
+      foo
+    </mark>
+    /bar
+  </React.Fragment>
+</React.Fragment>
+`;
+
+exports[`should render correctly 3`] = `
+<React.Fragment>
+  <QualifierIcon
+    className="little-spacer-right"
+    qualifier="DIR"
+  />
+  foo/bar
+</React.Fragment>
+`;