]> source.dussan.org Git - sonarqube.git/commitdiff
Fix a bug with the version badges when filtering on an event category
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>
Mon, 10 Jul 2017 15:49:11 +0000 (17:49 +0200)
committerGrégoire Aubert <gregoire.aubert@sonarsource.com>
Thu, 13 Jul 2017 12:34:17 +0000 (14:34 +0200)
server/sonar-web/src/main/js/apps/projectActivity/__tests__/__snapshots__/utils-test.js.snap
server/sonar-web/src/main/js/apps/projectActivity/__tests__/utils-test.js
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.js
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityAnalysesList-test.js [new file with mode: 0644]
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityApp-test.js
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityAnalysesList-test.js.snap [new file with mode: 0644]
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityApp-test.js.snap
server/sonar-web/src/main/js/apps/projectActivity/utils.js

index e9144bf2e1675604e107a4fd769a6981874b6b13..14647a212945509d1564a2b2f75077c7eff17e3e 100644 (file)
@@ -53,6 +53,108 @@ Array [
 ]
 `;
 
+exports[`getAnalysesByVersionByDay should also filter analysis based on the query 1`] = `
+Array [
+  Object {
+    "byDay": Object {
+      "2017-4-16": Array [
+        Object {
+          "date": 2017-05-16T05:09:59.000Z,
+          "events": Array [
+            Object {
+              "category": "VERSION",
+              "key": "AVyM9oI1HjR_PLDzRciU",
+              "name": "1.0",
+            },
+            Object {
+              "category": "QUALITY_PROFILE",
+              "key": "AVwQF7zXl-nNFgFWOJ3W",
+              "name": "Changes in 'Default - SonarSource conventions' (Java)",
+            },
+          ],
+          "key": "AVwQF7kwl-nNFgFWOJ3V",
+        },
+      ],
+      "2017-4-18": Array [
+        Object {
+          "date": 2017-05-18T12:13:07.000Z,
+          "events": Array [
+            Object {
+              "category": "QUALITY_PROFILE",
+              "key": "AVxZtC-N7841nF4RNEMJ",
+              "name": "Changes in 'Default - SonarSource conventions' (Java)",
+            },
+          ],
+          "key": "AVxZtCpH7841nF4RNEMI",
+        },
+      ],
+    },
+    "key": "AVyM9oI1HjR_PLDzRciU",
+    "version": "1.0",
+  },
+  Object {
+    "byDay": Object {},
+    "key": undefined,
+    "version": undefined,
+  },
+]
+`;
+
+exports[`getAnalysesByVersionByDay should also filter analysis based on the query 2`] = `
+Array [
+  Object {
+    "byDay": Object {
+      "2017-5-9": Array [
+        Object {
+          "date": 2017-06-09T09:12:27.000Z,
+          "events": Array [
+            Object {
+              "category": "VERSION",
+              "key": "AVyM9oI1HjR_PLDzRciU",
+              "name": "1.1-SNAPSHOT",
+            },
+          ],
+          "key": "AVyM9n3cHjR_PLDzRciT",
+        },
+      ],
+    },
+    "key": "AVyM9oI1HjR_PLDzRciU",
+    "version": "1.1-SNAPSHOT",
+  },
+  Object {
+    "byDay": Object {
+      "2017-4-18": Array [
+        Object {
+          "date": 2017-05-18T12:13:07.000Z,
+          "events": Array [
+            Object {
+              "category": "QUALITY_PROFILE",
+              "key": "AVxZtC-N7841nF4RNEMJ",
+              "name": "Changes in 'Default - SonarSource conventions' (Java)",
+            },
+          ],
+          "key": "AVxZtCpH7841nF4RNEMI",
+        },
+      ],
+      "2017-5-9": Array [
+        Object {
+          "date": 2017-06-09T09:12:27.000Z,
+          "events": Array [],
+          "key": "AVyMjlK1HjR_PLDzRbB9",
+        },
+      ],
+    },
+    "key": "AVyM9oI1HjR_PLDzRciU",
+    "version": "1.0",
+  },
+  Object {
+    "byDay": Object {},
+    "key": undefined,
+    "version": undefined,
+  },
+]
+`;
+
 exports[`getAnalysesByVersionByDay should correctly map analysis by versions and by days 1`] = `
 Array [
   Object {
index c165f9740b83cc0f7662522cc2f7734c4ea724a1..b3e4f2b28cfb8107f2351e2a0408a41687d134ce 100644 (file)
@@ -108,7 +108,34 @@ describe('generateSeries', () => {
 
 describe('getAnalysesByVersionByDay', () => {
   it('should correctly map analysis by versions and by days', () => {
-    expect(utils.getAnalysesByVersionByDay(ANALYSES)).toMatchSnapshot();
+    expect(
+      utils.getAnalysesByVersionByDay(ANALYSES, {
+        category: '',
+        customMetrics: [],
+        graph: 'overview',
+        project: 'foo'
+      })
+    ).toMatchSnapshot();
+  });
+  it('should also filter analysis based on the query', () => {
+    expect(
+      utils.getAnalysesByVersionByDay(ANALYSES, {
+        category: 'QUALITY_PROFILE',
+        customMetrics: [],
+        graph: 'overview',
+        project: 'foo'
+      })
+    ).toMatchSnapshot();
+    expect(
+      utils.getAnalysesByVersionByDay(ANALYSES, {
+        category: '',
+        customMetrics: [],
+        graph: 'overview',
+        project: 'foo',
+        to: new Date('2017-06-09T11:12:27+0200'),
+        from: new Date('2017-05-18T14:13:07+0200')
+      })
+    ).toMatchSnapshot();
   });
 });
 
index a0a8a41dd318c5dea54af56d081b4b3b9e098590..2706f9d2b14539cf44a79913bef1d2709faabe35 100644 (file)
@@ -65,30 +65,48 @@ export default class ProjectActivityAnalysesList extends React.PureComponent {
   }
 
   componentDidUpdate(prevProps: Props) {
-    if (this.scrollContainer) {
-      const selectedDateChanged = selectedDateQueryChanged(prevProps.query, this.props.query);
-      if (selectedDateChanged || prevProps.analysis !== this.props.analyses) {
-        if (selectedDateChanged && this.props.query.selectedDate) {
-          const selectedDate = this.props.query.selectedDate.valueOf();
-          for (let i = 1; i < this.analyses.length; i++) {
-            if (Number(this.analyses[i].getAttribute('data-date')) === selectedDate) {
-              const containerHeight = this.scrollContainer.offsetHeight - 100;
-              const scrollDiff = Math.abs(
-                this.scrollContainer.scrollTop - this.analyses[i].offsetTop
-              );
-              // Center only the extremities and the ones outside of the container
-              if (scrollDiff > containerHeight || scrollDiff < 100) {
-                this.resetScrollTop(this.analyses[i].offsetTop - containerHeight / 2);
-              }
-              break;
-            }
-          }
-        } else if (activityQueryChanged(prevProps.query, this.props.query)) {
-          this.resetScrollTop(0, true);
+    if (!this.scrollContainer) {
+      return;
+    }
+    if (
+      this.props.query.selectedDate &&
+      (selectedDateQueryChanged(prevProps.query, this.props.query) ||
+        prevProps.analyses !== this.props.analyses)
+    ) {
+      this.scrollToDate(this.props.query.selectedDate);
+    } else if (activityQueryChanged(prevProps.query, this.props.query)) {
+      this.resetScrollTop(0, true);
+    }
+  }
+
+  handleScroll = () => this.updateStickyBadges(true);
+
+  resetScrollTop = (newScrollTop: number, forceBadgeAlignement?: boolean) => {
+    this.scrollContainer.scrollTop = newScrollTop;
+    for (let i = 1; i < this.badges.length; i++) {
+      this.badges[i].removeAttribute('originOffsetTop');
+      this.badges[i].classList.remove('sticky');
+    }
+    this.updateStickyBadges(forceBadgeAlignement);
+  };
+
+  scrollToDate = (targetDate: ?Date) => {
+    if (!this.scrollContainer || !targetDate) {
+      return;
+    }
+    const date = targetDate.valueOf();
+    for (let i = 1; i < this.analyses.length; i++) {
+      if (Number(this.analyses[i].getAttribute('data-date')) === date) {
+        const containerHeight = this.scrollContainer.offsetHeight - 100;
+        const scrollDiff = Math.abs(this.scrollContainer.scrollTop - this.analyses[i].offsetTop);
+        // Center only the extremities and the ones outside of the container
+        if (scrollDiff > containerHeight || scrollDiff < 100) {
+          this.resetScrollTop(this.analyses[i].offsetTop - containerHeight / 2);
         }
+        break;
       }
     }
-  }
+  };
 
   updateStickyBadges = (forceBadgeAlignement?: boolean) => {
     if (this.scrollContainer && this.badges) {
@@ -119,23 +137,14 @@ export default class ProjectActivityAnalysesList extends React.PureComponent {
     }
   };
 
-  handleScroll = () => this.updateStickyBadges(true);
-
-  resetScrollTop = (newScrollTop: number, forceBadgeAlignement?: boolean) => {
-    this.scrollContainer.scrollTop = newScrollTop;
-    for (let i = 1; i < this.badges.length; i++) {
-      this.badges[i].removeAttribute('originOffsetTop');
-      this.badges[i].classList.remove('sticky');
-    }
-    this.updateStickyBadges(forceBadgeAlignement);
-  };
-
-  updateSelectedDate = (date: Date) => {
-    this.props.updateQuery({ selectedDate: date });
-  };
+  updateSelectedDate = (date: Date) => this.props.updateQuery({ selectedDate: date });
 
   render() {
-    if (this.props.analyses.length === 0) {
+    const byVersionByDay = getAnalysesByVersionByDay(this.props.analyses, this.props.query);
+    const hasFilteredData =
+      byVersionByDay.length > 1 ||
+      (byVersionByDay.length === 1 && Object.keys(byVersionByDay[0].byDay).length > 0);
+    if (this.props.analyses.length === 0 || !hasFilteredData) {
       return (
         <div className={this.props.className}>
           {this.props.loading
@@ -146,7 +155,6 @@ export default class ProjectActivityAnalysesList extends React.PureComponent {
     }
 
     const firstAnalysisKey = this.props.analyses[0].key;
-    const byVersionByDay = getAnalysesByVersionByDay(this.props.analyses);
     const selectedDate = this.props.query.selectedDate
       ? this.props.query.selectedDate.valueOf()
       : null;
@@ -155,46 +163,52 @@ export default class ProjectActivityAnalysesList extends React.PureComponent {
         className={classNames('project-activity-versions-list', this.props.className)}
         onScroll={this.handleScroll}
         ref={element => (this.scrollContainer = element)}>
-        {byVersionByDay.map((version, idx) => (
-          <li key={version.key || 'noversion'}>
-            {version.version &&
-              <div className={classNames('project-activity-version-badge', { first: idx === 0 })}>
-                <span className="badge">
-                  {version.version}
-                </span>
-              </div>}
-            <ul className="project-activity-days-list">
-              {Object.keys(version.byDay).map(day => (
-                <li
-                  key={day}
-                  className="project-activity-day"
-                  data-day={moment(Number(day)).format('YYYY-MM-DD')}>
-                  <div className="project-activity-date">
-                    <FormattedDate date={Number(day)} format="LL" />
-                  </div>
-                  <ul className="project-activity-analyses-list">
-                    {version.byDay[day] != null &&
-                      version.byDay[day].map(analysis => (
-                        <ProjectActivityAnalysis
-                          addCustomEvent={this.props.addCustomEvent}
-                          addVersion={this.props.addVersion}
-                          analysis={analysis}
-                          canAdmin={this.props.canAdmin}
-                          changeEvent={this.props.changeEvent}
-                          deleteAnalysis={this.props.deleteAnalysis}
-                          deleteEvent={this.props.deleteEvent}
-                          isFirst={analysis.key === firstAnalysisKey}
-                          key={analysis.key}
-                          selected={analysis.date.valueOf() === selectedDate}
-                          updateSelectedDate={this.updateSelectedDate}
-                        />
-                      ))}
-                  </ul>
-                </li>
-              ))}
-            </ul>
-          </li>
-        ))}
+        {byVersionByDay.map((version, idx) => {
+          const days = Object.keys(version.byDay);
+          if (days.length <= 0) {
+            return null;
+          }
+          return (
+            <li key={version.key || 'noversion'}>
+              {version.version &&
+                <div className={classNames('project-activity-version-badge', { first: idx === 0 })}>
+                  <span className="badge">
+                    {version.version}
+                  </span>
+                </div>}
+              <ul className="project-activity-days-list">
+                {days.map(day => (
+                  <li
+                    key={day}
+                    className="project-activity-day"
+                    data-day={moment(Number(day)).format('YYYY-MM-DD')}>
+                    <div className="project-activity-date">
+                      <FormattedDate date={Number(day)} format="LL" />
+                    </div>
+                    <ul className="project-activity-analyses-list">
+                      {version.byDay[day] != null &&
+                        version.byDay[day].map(analysis => (
+                          <ProjectActivityAnalysis
+                            addCustomEvent={this.props.addCustomEvent}
+                            addVersion={this.props.addVersion}
+                            analysis={analysis}
+                            canAdmin={this.props.canAdmin}
+                            changeEvent={this.props.changeEvent}
+                            deleteAnalysis={this.props.deleteAnalysis}
+                            deleteEvent={this.props.deleteEvent}
+                            isFirst={analysis.key === firstAnalysisKey}
+                            key={analysis.key}
+                            selected={analysis.date.valueOf() === selectedDate}
+                            updateSelectedDate={this.updateSelectedDate}
+                          />
+                        ))}
+                    </ul>
+                  </li>
+                ))}
+              </ul>
+            </li>
+          );
+        })}
         {this.props.analysesLoading && <li className="text-center"><i className="spinner" /></li>}
       </ul>
     );
index 59c9485d937a057fa8c7171e9e9f8e18df83d293..e3a3b582796e63907d3c221adc2cda6165246678 100644 (file)
@@ -24,7 +24,7 @@ import moment from 'moment';
 import ProjectActivityPageHeader from './ProjectActivityPageHeader';
 import ProjectActivityAnalysesList from './ProjectActivityAnalysesList';
 import ProjectActivityGraphs from './ProjectActivityGraphs';
-import { getDisplayedHistoryMetrics, activityQueryChanged } from '../utils';
+import { getDisplayedHistoryMetrics } from '../utils';
 import { translate } from '../../../helpers/l10n';
 import './projectActivity.css';
 import type { Analysis, MeasureHistory, Metric, Query } from '../types';
@@ -46,40 +46,8 @@ type Props = {
   updateQuery: (newQuery: Query) => void
 };
 
-type State = {
-  filteredAnalyses: Array<Analysis>
-};
-
 export default class ProjectActivityApp extends React.PureComponent {
   props: Props;
-  state: State;
-
-  constructor(props: Props) {
-    super(props);
-    this.state = { filteredAnalyses: this.filterAnalyses(props.analyses, props.query) };
-  }
-
-  componentWillReceiveProps(nextProps: Props) {
-    if (
-      nextProps.analyses !== this.props.analyses ||
-      activityQueryChanged(this.props.query, nextProps.query)
-    ) {
-      this.setState({ filteredAnalyses: this.filterAnalyses(nextProps.analyses, nextProps.query) });
-    }
-  }
-
-  filterAnalyses = (analyses: Array<Analysis>, query: Query): Array<Analysis> => {
-    if (!query.category && !query.from && !query.to) {
-      return analyses;
-    }
-    return analyses.filter(analysis => {
-      const isAfterFrom = !query.from || analysis.date >= query.from;
-      const isBeforeTo = !query.to || analysis.date <= query.to;
-      const hasSelectedCategoryEvents =
-        !query.category || analysis.events.find(event => event.category === query.category) != null;
-      return isAfterFrom && isBeforeTo && hasSelectedCategoryEvents;
-    });
-  };
 
   getMetricType = () => {
     const historyMetrics = getDisplayedHistoryMetrics(
@@ -92,8 +60,7 @@ export default class ProjectActivityApp extends React.PureComponent {
   };
 
   render() {
-    const { measuresHistory, query } = this.props;
-    const { filteredAnalyses } = this.state;
+    const { analyses, measuresHistory, query } = this.props;
     const { configuration } = this.props.project;
     const canAdmin = configuration ? configuration.showHistory : false;
     return (
@@ -113,7 +80,7 @@ export default class ProjectActivityApp extends React.PureComponent {
               addCustomEvent={this.props.addCustomEvent}
               addVersion={this.props.addVersion}
               analysesLoading={this.props.analysesLoading}
-              analyses={filteredAnalyses}
+              analyses={analyses}
               canAdmin={canAdmin}
               className="boxed-group-inner"
               changeEvent={this.props.changeEvent}
@@ -126,7 +93,7 @@ export default class ProjectActivityApp extends React.PureComponent {
           </div>
           <div className="project-activity-layout-page-main">
             <ProjectActivityGraphs
-              analyses={filteredAnalyses}
+              analyses={analyses}
               leakPeriodDate={moment(this.props.project.leakPeriodDate).toDate()}
               loading={this.props.graphLoading}
               measuresHistory={measuresHistory}
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityAnalysesList-test.js b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityAnalysesList-test.js
new file mode 100644 (file)
index 0000000..762c2d5
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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 React from 'react';
+import { shallow } from 'enzyme';
+import ProjectActivityAnalysesList from '../ProjectActivityAnalysesList';
+
+const ANALYSES = [
+  {
+    key: 'A1',
+    date: new Date('2016-10-27T16:33:50+0000'),
+    events: [
+      {
+        key: 'E1',
+        category: 'VERSION',
+        name: '6.5-SNAPSHOT'
+      }
+    ]
+  },
+  {
+    key: 'A2',
+    date: new Date('2016-10-27T12:21:15+0000'),
+    events: []
+  },
+  {
+    key: 'A3',
+    date: new Date('2016-10-26T12:17:29+0000'),
+    events: [
+      {
+        key: 'E2',
+        category: 'VERSION',
+        name: '6.4'
+      },
+      {
+        key: 'E3',
+        category: 'OTHER',
+        name: 'foo'
+      }
+    ]
+  },
+  {
+    key: 'A4',
+    date: new Date('2016-10-24T16:33:50+0000'),
+    events: [
+      {
+        key: 'E1',
+        category: 'QUALITY_GATE',
+        name: 'Quality gate changed to red...'
+      }
+    ]
+  }
+];
+
+const DEFAULT_PROPS = {
+  addCustomEvent: () => {},
+  addVersion: () => {},
+  analyses: ANALYSES,
+  analysesLoading: false,
+  canAdmin: false,
+  changeEvent: () => {},
+  deleteAnalysis: () => {},
+  deleteEvent: () => {},
+  loading: false,
+  query: { category: '', graph: 'overview', project: 'org.sonarsource.sonarqube:sonarqube' },
+  updateQuery: () => {}
+};
+
+jest.mock('moment', () => date => ({
+  startOf: () => {
+    return {
+      valueOf: () => `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`
+    };
+  },
+  toDate: () => new Date(date),
+  format: format => `Formated.${format}:${date}`
+}));
+
+window.Number = val => val;
+
+it('should render correctly', () => {
+  expect(shallow(<ProjectActivityAnalysesList {...DEFAULT_PROPS} />)).toMatchSnapshot();
+});
+
+it('should correctly filter analyses by category', () => {
+  const wrapper = shallow(<ProjectActivityAnalysesList {...DEFAULT_PROPS} />);
+  wrapper.setProps({ query: { ...DEFAULT_PROPS.query, category: 'QUALITY_GATE' } });
+  expect(wrapper).toMatchSnapshot();
+});
+
+it('should correctly filter analyses by date range', () => {
+  const wrapper = shallow(<ProjectActivityAnalysesList {...DEFAULT_PROPS} />);
+  wrapper.setProps({
+    query: {
+      ...DEFAULT_PROPS.query,
+      from: new Date('2016-10-27T16:33:50+0000'),
+      to: new Date('2016-10-27T16:33:50+0000')
+    }
+  });
+  expect(wrapper).toMatchSnapshot();
+});
index 22f85b2a28f8b3c32d5559773aadadb3db54bd8b..21c0a40d10c34b8bf95c0563d577638d52f51d33 100644 (file)
@@ -18,7 +18,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import React from 'react';
-import { mount, shallow } from 'enzyme';
+import { shallow } from 'enzyme';
 import ProjectActivityApp from '../ProjectActivityApp';
 
 const ANALYSES = [
@@ -87,21 +87,3 @@ const DEFAULT_PROPS = {
 it('should render correctly', () => {
   expect(shallow(<ProjectActivityApp {...DEFAULT_PROPS} />)).toMatchSnapshot();
 });
-
-it('should correctly filter analyses by category', () => {
-  const wrapper = mount(<ProjectActivityApp {...DEFAULT_PROPS} />);
-  wrapper.setProps({ query: { ...DEFAULT_PROPS.query, category: 'VERSION' } });
-  expect(wrapper.state()).toMatchSnapshot();
-});
-
-it('should correctly filter analyses by date range', () => {
-  const wrapper = mount(<ProjectActivityApp {...DEFAULT_PROPS} />);
-  wrapper.setProps({
-    query: {
-      ...DEFAULT_PROPS.query,
-      from: new Date('2016-10-27T12:21:15+0200'),
-      to: new Date('2016-10-27T12:21:15+0200')
-    }
-  });
-  expect(wrapper.state()).toMatchSnapshot();
-});
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityAnalysesList-test.js.snap b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityAnalysesList-test.js.snap
new file mode 100644 (file)
index 0000000..53dc51e
--- /dev/null
@@ -0,0 +1,336 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should correctly filter analyses by category 1`] = `
+<ul
+  className="project-activity-versions-list"
+  onScroll={[Function]}
+>
+  <li>
+    <div
+      className="project-activity-version-badge first"
+    >
+      <span
+        className="badge"
+      >
+        6.4
+      </span>
+    </div>
+    <ul
+      className="project-activity-days-list"
+    >
+      <li
+        className="project-activity-day"
+        data-day="Formated.YYYY-MM-DD:2016-9-24"
+      >
+        <div
+          className="project-activity-date"
+        >
+          <FormattedDate
+            date="2016-9-24"
+            format="LL"
+          />
+        </div>
+        <ul
+          className="project-activity-analyses-list"
+        >
+          <ProjectActivityAnalysis
+            addCustomEvent={[Function]}
+            addVersion={[Function]}
+            analysis={
+              Object {
+                "date": 2016-10-24T16:33:50.000Z,
+                "events": Array [
+                  Object {
+                    "category": "QUALITY_GATE",
+                    "key": "E1",
+                    "name": "Quality gate changed to red...",
+                  },
+                ],
+                "key": "A4",
+              }
+            }
+            canAdmin={false}
+            changeEvent={[Function]}
+            deleteAnalysis={[Function]}
+            deleteEvent={[Function]}
+            isFirst={false}
+            selected={false}
+            updateSelectedDate={[Function]}
+          />
+        </ul>
+      </li>
+    </ul>
+  </li>
+</ul>
+`;
+
+exports[`should correctly filter analyses by date range 1`] = `
+<ul
+  className="project-activity-versions-list"
+  onScroll={[Function]}
+>
+  <li>
+    <div
+      className="project-activity-version-badge first"
+    >
+      <span
+        className="badge"
+      >
+        6.5-SNAPSHOT
+      </span>
+    </div>
+    <ul
+      className="project-activity-days-list"
+    >
+      <li
+        className="project-activity-day"
+        data-day="Formated.YYYY-MM-DD:2016-9-27"
+      >
+        <div
+          className="project-activity-date"
+        >
+          <FormattedDate
+            date="2016-9-27"
+            format="LL"
+          />
+        </div>
+        <ul
+          className="project-activity-analyses-list"
+        >
+          <ProjectActivityAnalysis
+            addCustomEvent={[Function]}
+            addVersion={[Function]}
+            analysis={
+              Object {
+                "date": 2016-10-27T16:33:50.000Z,
+                "events": Array [
+                  Object {
+                    "category": "VERSION",
+                    "key": "E1",
+                    "name": "6.5-SNAPSHOT",
+                  },
+                ],
+                "key": "A1",
+              }
+            }
+            canAdmin={false}
+            changeEvent={[Function]}
+            deleteAnalysis={[Function]}
+            deleteEvent={[Function]}
+            isFirst={true}
+            selected={false}
+            updateSelectedDate={[Function]}
+          />
+        </ul>
+      </li>
+    </ul>
+  </li>
+</ul>
+`;
+
+exports[`should render correctly 1`] = `
+<ul
+  className="project-activity-versions-list"
+  onScroll={[Function]}
+>
+  <li>
+    <div
+      className="project-activity-version-badge first"
+    >
+      <span
+        className="badge"
+      >
+        6.5-SNAPSHOT
+      </span>
+    </div>
+    <ul
+      className="project-activity-days-list"
+    >
+      <li
+        className="project-activity-day"
+        data-day="Formated.YYYY-MM-DD:2016-9-27"
+      >
+        <div
+          className="project-activity-date"
+        >
+          <FormattedDate
+            date="2016-9-27"
+            format="LL"
+          />
+        </div>
+        <ul
+          className="project-activity-analyses-list"
+        >
+          <ProjectActivityAnalysis
+            addCustomEvent={[Function]}
+            addVersion={[Function]}
+            analysis={
+              Object {
+                "date": 2016-10-27T16:33:50.000Z,
+                "events": Array [
+                  Object {
+                    "category": "VERSION",
+                    "key": "E1",
+                    "name": "6.5-SNAPSHOT",
+                  },
+                ],
+                "key": "A1",
+              }
+            }
+            canAdmin={false}
+            changeEvent={[Function]}
+            deleteAnalysis={[Function]}
+            deleteEvent={[Function]}
+            isFirst={true}
+            selected={false}
+            updateSelectedDate={[Function]}
+          />
+        </ul>
+      </li>
+    </ul>
+  </li>
+  <li>
+    <div
+      className="project-activity-version-badge"
+    >
+      <span
+        className="badge"
+      >
+        6.4
+      </span>
+    </div>
+    <ul
+      className="project-activity-days-list"
+    >
+      <li
+        className="project-activity-day"
+        data-day="Formated.YYYY-MM-DD:2016-9-27"
+      >
+        <div
+          className="project-activity-date"
+        >
+          <FormattedDate
+            date="2016-9-27"
+            format="LL"
+          />
+        </div>
+        <ul
+          className="project-activity-analyses-list"
+        >
+          <ProjectActivityAnalysis
+            addCustomEvent={[Function]}
+            addVersion={[Function]}
+            analysis={
+              Object {
+                "date": 2016-10-27T12:21:15.000Z,
+                "events": Array [],
+                "key": "A2",
+              }
+            }
+            canAdmin={false}
+            changeEvent={[Function]}
+            deleteAnalysis={[Function]}
+            deleteEvent={[Function]}
+            isFirst={false}
+            selected={false}
+            updateSelectedDate={[Function]}
+          />
+        </ul>
+      </li>
+      <li
+        className="project-activity-day"
+        data-day="Formated.YYYY-MM-DD:2016-9-26"
+      >
+        <div
+          className="project-activity-date"
+        >
+          <FormattedDate
+            date="2016-9-26"
+            format="LL"
+          />
+        </div>
+        <ul
+          className="project-activity-analyses-list"
+        >
+          <ProjectActivityAnalysis
+            addCustomEvent={[Function]}
+            addVersion={[Function]}
+            analysis={
+              Object {
+                "date": 2016-10-26T12:17:29.000Z,
+                "events": Array [
+                  Object {
+                    "category": "VERSION",
+                    "key": "E2",
+                    "name": "6.4",
+                  },
+                  Object {
+                    "category": "OTHER",
+                    "key": "E3",
+                    "name": "foo",
+                  },
+                ],
+                "key": "A3",
+              }
+            }
+            canAdmin={false}
+            changeEvent={[Function]}
+            deleteAnalysis={[Function]}
+            deleteEvent={[Function]}
+            isFirst={false}
+            selected={false}
+            updateSelectedDate={[Function]}
+          />
+        </ul>
+      </li>
+    </ul>
+  </li>
+  <li>
+    <ul
+      className="project-activity-days-list"
+    >
+      <li
+        className="project-activity-day"
+        data-day="Formated.YYYY-MM-DD:2016-9-24"
+      >
+        <div
+          className="project-activity-date"
+        >
+          <FormattedDate
+            date="2016-9-24"
+            format="LL"
+          />
+        </div>
+        <ul
+          className="project-activity-analyses-list"
+        >
+          <ProjectActivityAnalysis
+            addCustomEvent={[Function]}
+            addVersion={[Function]}
+            analysis={
+              Object {
+                "date": 2016-10-24T16:33:50.000Z,
+                "events": Array [
+                  Object {
+                    "category": "QUALITY_GATE",
+                    "key": "E1",
+                    "name": "Quality gate changed to red...",
+                  },
+                ],
+                "key": "A4",
+              }
+            }
+            canAdmin={false}
+            changeEvent={[Function]}
+            deleteAnalysis={[Function]}
+            deleteEvent={[Function]}
+            isFirst={false}
+            selected={false}
+            updateSelectedDate={[Function]}
+          />
+        </ul>
+      </li>
+    </ul>
+  </li>
+</ul>
+`;
index 7fa450f12c8cd451556cdb0086e5406b14202d70..f966955c2482ca0be4a6ab17ef522bfe5c5d9c00 100644 (file)
@@ -1,51 +1,5 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`should correctly filter analyses by category 1`] = `
-Object {
-  "filteredAnalyses": Array [
-    Object {
-      "date": 2016-10-27T14:33:50.000Z,
-      "events": Array [
-        Object {
-          "category": "VERSION",
-          "key": "E1",
-          "name": "6.5-SNAPSHOT",
-        },
-      ],
-      "key": "A1",
-    },
-    Object {
-      "date": 2016-10-26T10:17:29.000Z,
-      "events": Array [
-        Object {
-          "category": "VERSION",
-          "key": "E2",
-          "name": "6.4",
-        },
-        Object {
-          "category": "OTHER",
-          "key": "E3",
-          "name": "foo",
-        },
-      ],
-      "key": "A3",
-    },
-  ],
-}
-`;
-
-exports[`should correctly filter analyses by date range 1`] = `
-Object {
-  "filteredAnalyses": Array [
-    Object {
-      "date": 2016-10-27T10:21:15.000Z,
-      "events": Array [],
-      "key": "A2",
-    },
-  ],
-}
-`;
-
 exports[`should render correctly 1`] = `
 <div
   className="page page-limited"
index a42c389972c70069e9479bafc088bdd34768ca3e..6ea4c782138e9eb397055a33e6eefa6a3d681d80 100644 (file)
@@ -130,7 +130,8 @@ export const generateSeries = (
 };
 
 export const getAnalysesByVersionByDay = (
-  analyses: Array<Analysis>
+  analyses: Array<Analysis>,
+  query: Query
 ): Array<{
   version: ?string,
   key: ?string,
@@ -142,16 +143,30 @@ export const getAnalysesByVersionByDay = (
     }
     const currentVersion = acc[acc.length - 1];
     const day = moment(analysis.date).startOf('day').valueOf().toString();
-    if (!currentVersion.byDay[day]) {
-      currentVersion.byDay[day] = [];
+
+    let matchFilters = true;
+    if (query.category || query.from || query.to) {
+      const isAfterFrom = !query.from || analysis.date >= query.from;
+      const isBeforeTo = !query.to || analysis.date <= query.to;
+      const hasSelectedCategoryEvents =
+        !query.category || analysis.events.find(event => event.category === query.category) != null;
+      matchFilters = isAfterFrom && isBeforeTo && hasSelectedCategoryEvents;
+    }
+
+    if (matchFilters) {
+      if (!currentVersion.byDay[day]) {
+        currentVersion.byDay[day] = [];
+      }
+      currentVersion.byDay[day].push(analysis);
     }
-    currentVersion.byDay[day].push(analysis);
 
     const versionEvent = analysis.events.find(event => event.category === 'VERSION');
     if (versionEvent && versionEvent.category === 'VERSION') {
       currentVersion.version = versionEvent.name;
       currentVersion.key = versionEvent.key;
-      acc.push({ version: undefined, key: undefined, byDay: {} });
+      if (Object.keys(currentVersion.byDay).length > 0) {
+        acc.push({ version: undefined, key: undefined, byDay: {} });
+      }
     }
     return acc;
   }, []);