]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5726 SONAR-6234 cover some corner cases, add tests
authorStas Vilchik <vilchiks@gmail.com>
Wed, 4 Mar 2015 15:36:56 +0000 (16:36 +0100)
committerStas Vilchik <vilchiks@gmail.com>
Wed, 4 Mar 2015 15:41:30 +0000 (16:41 +0100)
24 files changed:
server/sonar-web/Gruntfile.coffee
server/sonar-web/src/main/hbs/widgets/widget-issue-filter-severities.hbs
server/sonar-web/src/main/js/widgets/issue-filter.js
server/sonar-web/src/test/js/global-issue-filter-widget.js [new file with mode: 0644]
server/sonar-web/src/test/js/project-issue-filter-widget.js [new file with mode: 0644]
server/sonar-web/src/test/json/global-issues-filter-widget/all-issues-by-resolution.json [new file with mode: 0644]
server/sonar-web/src/test/json/global-issues-filter-widget/all-issues-by-status.json [new file with mode: 0644]
server/sonar-web/src/test/json/global-issues-filter-widget/red-issues-by-severity.json [new file with mode: 0644]
server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-action-plan.json [new file with mode: 0644]
server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-assignee.json [new file with mode: 0644]
server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-date-limited.json [new file with mode: 0644]
server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-date.json [new file with mode: 0644]
server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-language.json [new file with mode: 0644]
server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-project.json [new file with mode: 0644]
server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-resolution.json [new file with mode: 0644]
server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-rule.json [new file with mode: 0644]
server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-severity.json [new file with mode: 0644]
server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-unassigned-issues-by-assignee.json [new file with mode: 0644]
server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-unplanned-issues-by-action-plan.json [new file with mode: 0644]
server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-date.json [new file with mode: 0644]
server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-severity-with-differential-period.json [new file with mode: 0644]
server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-severity.json [new file with mode: 0644]
server/sonar-web/src/test/lib.js
server/sonar-web/src/test/views/issue-filter-widget.jade [new file with mode: 0644]

index 852d958474bbc05e5d32deed78fb593b05105a91..57b0b7f30dca9b630d48f0f10de059f1f56970c9 100644 (file)
@@ -357,6 +357,13 @@ module.exports = (grunt) ->
           concise: true
           port: expressPort
         src: ['src/test/js/**/*.js']
+      testCoverageTemp:
+        options:
+          test: true
+          'fail-fast': true
+          verbose: true
+          port: expressPort
+        src: ['src/test/js/**/*-issue-filter-widget.js']
       single:
         options:
           test: true
@@ -465,6 +472,9 @@ module.exports = (grunt) ->
   grunt.registerTask 'testCoverage',
       ['dev', 'express:testCoverage', 'curl:resetCoverage', 'casper:testCoverage', 'curl:downloadCoverage', 'unzip', 'replace:lcov']
 
+  grunt.registerTask 'testCoverageTemp',
+      ['dev', 'express:testCoverage', 'curl:resetCoverage', 'casper:testCoverageTemp', 'curl:downloadCoverage', 'unzip', 'replace:lcov']
+
   grunt.registerTask 'single',
       ['dev', 'express:test', 'casper:single']
 
index c18b9ecbe82b2e59709718128e9e7463950e7f83..98b255ce6404bfd4bdce75997f4fe4b8d66539dc 100644 (file)
@@ -1,9 +1,9 @@
 <table class="data zebra">
   <tr>
     <td>
-      <a href="{{link '/issues/search#' query}}"><strong>{{t 'total'}}</strong></a>
+      <a href="{{issueFilterTotalLink parsedQuery}}"><strong>{{t 'total'}}</strong></a>
     </td>
-    <td class="text-right"><strong>{{total}}</strong></td>
+    <td class="text-right"><strong>{{#notNull periodDate}}+{{/notNull}}{{total}}</strong></td>
   </tr>
   {{#each items}}
     <tr>
index 2e40e16578c64c283db68e8f35264623a1e1ccb6..85a62dcb6c1d3a9f83f0dee2c3eab45fb750e957 100644 (file)
@@ -81,6 +81,13 @@ define(['templates/widgets'], function () {
                 return user.name;
               }
             }
+          },
+          filter: function (item) {
+            if ('' + this.query.assigned === 'false') {
+              return item.val === '';
+            } else {
+              return defaultFilter.call(this, item);
+            }
           }
         },
         'languages': {
@@ -102,6 +109,13 @@ define(['templates/widgets'], function () {
                 return actionPlan.name;
               }
             }
+          },
+          filter: function (item) {
+            if ('' + this.query.planned === 'false') {
+              return item.val === '';
+            } else {
+              return defaultFilter.call(this, item);
+            }
           }
         },
         'createdAt': {
diff --git a/server/sonar-web/src/test/js/global-issue-filter-widget.js b/server/sonar-web/src/test/js/global-issue-filter-widget.js
new file mode 100644 (file)
index 0000000..ac2f5f7
--- /dev/null
@@ -0,0 +1,853 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.
+ */
+/* globals casper: false */
+
+var lib = require('../lib'),
+    testName = lib.testName('Global Issue Filter Widget');
+
+
+lib.initMessages();
+lib.changeWorkingDirectory('global-issues-filter-widget');
+lib.configureCasper();
+
+
+casper.test.begin(testName('Unresolved Issues By Severity'), 13, function (test) {
+  casper
+      .start(lib.buildUrl('issue-filter-widget'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequest('/api/l10n/index', '{}');
+        lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-severity.json',
+            { data: { resolved: 'false' } });
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+            window.requestMessages().done(function () {
+              new IssueFilter({
+                el: '#issue-filter-widget',
+                query: 'resolved=false',
+                distributionAxis: 'severities'
+              });
+            });
+          });
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('#issue-filter-widget > table');
+      })
+
+      .then(function () {
+        // check count
+        test.assertElementCount('tr', 6);
+
+        // check order and values
+        test.assertSelectorContains('tr:nth-child(1)', '6851');
+        test.assertSelectorContains('tr:nth-child(2)', '1');
+        test.assertSelectorContains('tr:nth-child(3)', '105');
+        test.assertSelectorContains('tr:nth-child(4)', '5027');
+        test.assertSelectorContains('tr:nth-child(5)', '540');
+        test.assertSelectorContains('tr:nth-child(6)', '1178');
+
+        // check links
+        test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false"]');
+        test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|severities=BLOCKER"]');
+        test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|severities=CRITICAL"]');
+        test.assertExists('tr:nth-child(4) a[href="/issues/search#resolved=false|severities=MAJOR"]');
+        test.assertExists('tr:nth-child(5) a[href="/issues/search#resolved=false|severities=MINOR"]');
+        test.assertExists('tr:nth-child(6) a[href="/issues/search#resolved=false|severities=INFO"]');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
+
+
+casper.test.begin(testName('Red Issues By Severity'), 9, function (test) {
+  casper
+      .start(lib.buildUrl('issue-filter-widget'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequest('/api/l10n/index', '{}');
+        lib.mockRequestFromFile('/api/issues/search', 'red-issues-by-severity.json',
+            { data: { resolved: 'false', severities: 'BLOCKER,CRITICAL,MAJOR' } });
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+            window.requestMessages().done(function () {
+              new IssueFilter({
+                el: '#issue-filter-widget',
+                query: 'resolved=false|severities=BLOCKER,CRITICAL,MAJOR',
+                distributionAxis: 'severities'
+              });
+            });
+          });
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('#issue-filter-widget > table');
+      })
+
+      .then(function () {
+        // check count
+        test.assertElementCount('tr', 4);
+
+        // check order and values
+        test.assertSelectorContains('tr:nth-child(1)', '6851');
+        test.assertSelectorContains('tr:nth-child(2)', '1');
+        test.assertSelectorContains('tr:nth-child(3)', '105');
+        test.assertSelectorContains('tr:nth-child(4)', '5027');
+
+        // check links
+        test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false|severities=BLOCKER%2CCRITICAL%2CMAJOR"]');
+        test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|severities=BLOCKER"]');
+        test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|severities=CRITICAL"]');
+        test.assertExists('tr:nth-child(4) a[href="/issues/search#resolved=false|severities=MAJOR"]');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
+
+
+casper.test.begin(testName('All Issues By Status'), 9, function (test) {
+  casper
+      .start(lib.buildUrl('issue-filter-widget'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequest('/api/l10n/index', '{}');
+        lib.mockRequestFromFile('/api/issues/search', 'all-issues-by-status.json');
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+            window.requestMessages().done(function () {
+              new IssueFilter({
+                el: '#issue-filter-widget',
+                query: '',
+                distributionAxis: 'statuses'
+              });
+            });
+          });
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('#issue-filter-widget > table');
+      })
+
+      .then(function () {
+        // check count
+        test.assertElementCount('tr', 6);
+
+        // check order and values
+        test.assertSelectorContains('tr:nth-child(1)', '71571');
+        test.assertSelectorContains('tr:nth-child(2)', '238');
+        test.assertSelectorContains('tr:nth-child(3)', '4');
+        test.assertSelectorContains('tr:nth-child(4)', '6609');
+        test.assertSelectorContains('tr:nth-child(5)', '1307');
+        test.assertSelectorContains('tr:nth-child(6)', '63.4k');
+
+        // check links
+        test.assertExists('tr:nth-child(1) a[href="/issues/search#"]');
+        test.assertExists('tr:nth-child(2) a[href="/issues/search#statuses=OPEN"]');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
+
+
+casper.test.begin(testName('All Issues By Resolution'), 10, function (test) {
+  casper
+      .start(lib.buildUrl('issue-filter-widget'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequest('/api/l10n/index', '{}');
+        lib.mockRequestFromFile('/api/issues/search', 'all-issues-by-resolution.json');
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+            window.requestMessages().done(function () {
+              new IssueFilter({
+                el: '#issue-filter-widget',
+                query: '',
+                distributionAxis: 'resolutions'
+              });
+            });
+          });
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('#issue-filter-widget > table');
+      })
+
+      .then(function () {
+        // check count
+        test.assertElementCount('tr', 6);
+
+        // check order and values
+        test.assertSelectorContains('tr:nth-child(1)', '71571');
+        test.assertSelectorContains('tr:nth-child(2)', '6851');
+        test.assertSelectorContains('tr:nth-child(3)', '752');
+        test.assertSelectorContains('tr:nth-child(4)', '550');
+        test.assertSelectorContains('tr:nth-child(5)', '47.1k');
+        test.assertSelectorContains('tr:nth-child(6)', '16.3k');
+
+        // check links
+        test.assertExists('tr:nth-child(1) a[href="/issues/search#"]');
+        test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false"]');
+        test.assertExists('tr:nth-child(3) a[href="/issues/search#resolutions=FALSE-POSITIVE"]');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
+
+
+casper.test.begin(testName('Unresolved Issues By Resolution'), 5, function (test) {
+  casper
+      .start(lib.buildUrl('issue-filter-widget'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequest('/api/l10n/index', '{}');
+        lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-resolution.json',
+            { data: { resolved: 'false' } });
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+            window.requestMessages().done(function () {
+              new IssueFilter({
+                el: '#issue-filter-widget',
+                query: 'resolved=false',
+                distributionAxis: 'resolutions'
+              });
+            });
+          });
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('#issue-filter-widget > table');
+      })
+
+      .then(function () {
+        // check count
+        test.assertElementCount('tr', 2);
+
+        // check order and values
+        test.assertSelectorContains('tr:nth-child(1)', '6851');
+        test.assertSelectorContains('tr:nth-child(2)', '6851');
+
+        // check links
+        test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false"]');
+        test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false"]');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
+
+
+casper.test.begin(testName('Unresolved Issues By Rule'), 15, function (test) {
+  casper
+      .start(lib.buildUrl('issue-filter-widget'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequest('/api/l10n/index', '{}');
+        lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-rule.json',
+            { data: { resolved: 'false' } });
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+            window.requestMessages().done(function () {
+              new IssueFilter({
+                el: '#issue-filter-widget',
+                query: 'resolved=false',
+                distributionAxis: 'rules'
+              });
+            });
+          });
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('#issue-filter-widget > table');
+      })
+
+      .then(function () {
+        // check count
+        test.assertElementCount('tr', 16);
+
+        // check order and values
+        test.assertSelectorContains('tr:nth-child(1)', '6851');
+        test.assertSelectorContains('tr:nth-child(2)', '879');
+        test.assertSelectorContains('tr:nth-child(3)', '571');
+        test.assertSelectorContains('tr:nth-child(15)', '113');
+        test.assertSelectorContains('tr:nth-child(16)', '111');
+
+        // check links
+        test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false"]');
+        test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|rules=squid%3AS1161"]');
+        test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|rules=squid%3AS1135"]');
+        test.assertExists('tr:nth-child(15) a[href="/issues/search#resolved=false|rules=squid%3AS1134"]');
+        test.assertExists('tr:nth-child(16) a[href="/issues/search#resolved=false|rules=squid%3AS1192"]');
+
+        // check labels
+        test.assertSelectorContains('tr:nth-child(2)', '@Override" annotation should be used');
+        test.assertSelectorContains('tr:nth-child(3)', 'TODO tags should be handled');
+        test.assertSelectorContains('tr:nth-child(15)', 'FIXME tags should be handled');
+        test.assertSelectorContains('tr:nth-child(16)', 'String literals should not be duplicated');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
+
+
+casper.test.begin(testName('Unresolved Issues By Project'), 15, function (test) {
+  casper
+      .start(lib.buildUrl('issue-filter-widget'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequest('/api/l10n/index', '{}');
+        lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-project.json',
+            { data: { resolved: 'false' } });
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+            window.requestMessages().done(function () {
+              new IssueFilter({
+                el: '#issue-filter-widget',
+                query: 'resolved=false',
+                distributionAxis: 'projectUuids'
+              });
+            });
+          });
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('#issue-filter-widget > table');
+      })
+
+      .then(function () {
+        // check count
+        test.assertElementCount('tr', 5);
+
+        // check order and values
+        test.assertSelectorContains('tr:nth-child(1)', '2598');
+        test.assertSelectorContains('tr:nth-child(2)', '1766');
+        test.assertSelectorContains('tr:nth-child(3)', '442');
+        test.assertSelectorContains('tr:nth-child(4)', '283');
+        test.assertSelectorContains('tr:nth-child(5)', '107');
+
+        // check links
+        test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false"]');
+        test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|projectUuids=69e57151-be0d-4157-adff-c06741d88879"]');
+        test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|projectUuids=dd7c3556-ce3f-42d0-a348-914a582dc944"]');
+        test.assertExists('tr:nth-child(4) a[href="/issues/search#resolved=false|projectUuids=5eab015a-1f76-4ba4-bd89-bf547132d673"]');
+        test.assertExists('tr:nth-child(5) a[href="/issues/search#resolved=false|projectUuids=c156940b-e3ec-43f6-9589-e3b75aa9ca32"]');
+
+        // check labels
+        test.assertSelectorContains('tr:nth-child(2)', 'SonarQube');
+        test.assertSelectorContains('tr:nth-child(3)', 'SonarQube Java');
+        test.assertSelectorContains('tr:nth-child(4)', 'JavaScript');
+        test.assertSelectorContains('tr:nth-child(5)', 'Python');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
+
+
+casper.test.begin(testName('Unresolved Issues By Assignee'), 15, function (test) {
+  casper
+      .start(lib.buildUrl('issue-filter-widget'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequest('/api/l10n/index', '{}');
+        lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-assignee.json',
+            { data: { resolved: 'false' } });
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+            window.requestMessages().done(function () {
+              new IssueFilter({
+                el: '#issue-filter-widget',
+                query: 'resolved=false',
+                distributionAxis: 'assignees'
+              });
+            });
+          });
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('#issue-filter-widget > table');
+      })
+
+      .then(function () {
+        // check count
+        test.assertElementCount('tr', 5);
+
+        // check order and values
+        test.assertSelectorContains('tr:nth-child(1)', '6851');
+        test.assertSelectorContains('tr:nth-child(2)', '4134');
+        test.assertSelectorContains('tr:nth-child(3)', '698');
+        test.assertSelectorContains('tr:nth-child(4)', '504');
+        test.assertSelectorContains('tr:nth-child(5)', '426');
+
+        // check links
+        test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false"]');
+        test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|assigned=false"]');
+        test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|assignees=first.user"]');
+        test.assertExists('tr:nth-child(4) a[href="/issues/search#resolved=false|assignees=second.user"]');
+        test.assertExists('tr:nth-child(5) a[href="/issues/search#resolved=false|assignees=third.user"]');
+
+        // check labels
+        test.assertSelectorContains('tr:nth-child(2)', 'unassigned');
+        test.assertSelectorContains('tr:nth-child(3)', 'First User');
+        test.assertSelectorContains('tr:nth-child(4)', 'Second User');
+        test.assertSelectorContains('tr:nth-child(5)', 'Third User');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
+
+
+casper.test.begin(testName('Unresolved Unassigned Issues By Assignee'), 6, function (test) {
+  casper
+      .start(lib.buildUrl('issue-filter-widget'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequest('/api/l10n/index', '{}');
+        lib.mockRequestFromFile('/api/issues/search', 'unresolved-unassigned-issues-by-assignee.json',
+            { data: { resolved: 'false', assigned: 'false' } });
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+            window.requestMessages().done(function () {
+              new IssueFilter({
+                el: '#issue-filter-widget',
+                query: 'resolved=false|assigned=false',
+                distributionAxis: 'assignees'
+              });
+            });
+          });
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('#issue-filter-widget > table');
+      })
+
+      .then(function () {
+        // check count
+        test.assertElementCount('tr', 2);
+
+        // check order and values
+        test.assertSelectorContains('tr:nth-child(1)', '4134');
+        test.assertSelectorContains('tr:nth-child(2)', '4134');
+
+        // check links
+        test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false|assigned=false"]');
+        test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|assigned=false"]');
+
+        // check labels
+        test.assertSelectorContains('tr:nth-child(2)', 'unassigned');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
+
+
+casper.test.begin(testName('Unresolved Issues By Language'), 15, function (test) {
+  casper
+      .start(lib.buildUrl('issue-filter-widget'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequest('/api/l10n/index', '{}');
+        lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-language.json',
+            { data: { resolved: 'false' } });
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+            window.requestMessages().done(function () {
+              new IssueFilter({
+                el: '#issue-filter-widget',
+                query: 'resolved=false',
+                distributionAxis: 'languages'
+              });
+            });
+          });
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('#issue-filter-widget > table');
+      })
+
+      .then(function () {
+        // check count
+        test.assertElementCount('tr', 5);
+
+        // check order and values
+        test.assertSelectorContains('tr:nth-child(1)', '6851');
+        test.assertSelectorContains('tr:nth-child(2)', '6336');
+        test.assertSelectorContains('tr:nth-child(3)', '444');
+        test.assertSelectorContains('tr:nth-child(4)', '22');
+        test.assertSelectorContains('tr:nth-child(5)', '15');
+
+        // check links
+        test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false"]');
+        test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|languages=java"]');
+        test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|languages=py"]');
+        test.assertExists('tr:nth-child(4) a[href="/issues/search#resolved=false|languages=php"]');
+        test.assertExists('tr:nth-child(5) a[href="/issues/search#resolved=false|languages=js"]');
+
+        // check labels
+        test.assertSelectorContains('tr:nth-child(2)', 'Java');
+        test.assertSelectorContains('tr:nth-child(3)', 'Python');
+        test.assertSelectorContains('tr:nth-child(4)', 'PHP');
+        test.assertSelectorContains('tr:nth-child(5)', 'JavaScript');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
+
+
+casper.test.begin(testName('Unresolved Issues By Action Plan'), 15, function (test) {
+  casper
+      .start(lib.buildUrl('issue-filter-widget'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequest('/api/l10n/index', '{}');
+        lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-action-plan.json',
+            { data: { resolved: 'false' } });
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+            window.requestMessages().done(function () {
+              new IssueFilter({
+                el: '#issue-filter-widget',
+                query: 'resolved=false',
+                distributionAxis: 'actionPlans'
+              });
+            });
+          });
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('#issue-filter-widget > table');
+      })
+
+      .then(function () {
+        // check count
+        test.assertElementCount('tr', 5);
+
+        // check order and values
+        test.assertSelectorContains('tr:nth-child(1)', '6851');
+        test.assertSelectorContains('tr:nth-child(2)', '5877');
+        test.assertSelectorContains('tr:nth-child(3)', '532');
+        test.assertSelectorContains('tr:nth-child(4)', '56');
+        test.assertSelectorContains('tr:nth-child(5)', '52');
+
+        // check links
+        test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false"]');
+        test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|planned=false"]');
+        test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|actionPlans=0cf48508-2fcd-4cb8-a50b-c5cd7c3decc0"]');
+        test.assertExists('tr:nth-child(4) a[href="/issues/search#resolved=false|actionPlans=1b9e7e52-ff58-40c1-80bf-f68429a3275e"]');
+        test.assertExists('tr:nth-child(5) a[href="/issues/search#resolved=false|actionPlans=8c1d5d01-948e-4670-a0d9-17c512979486"]');
+
+        // check labels
+        test.assertSelectorContains('tr:nth-child(2)', 'unplanned');
+        test.assertSelectorContains('tr:nth-child(3)', 'First Action Plan');
+        test.assertSelectorContains('tr:nth-child(4)', 'Second Action Plan');
+        test.assertSelectorContains('tr:nth-child(5)', 'Third Action Plan');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
+
+
+casper.test.begin(testName('Unresolved Unplanned Issues By Action Plan'), 6, function (test) {
+  casper
+      .start(lib.buildUrl('issue-filter-widget'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequest('/api/l10n/index', '{}');
+        lib.mockRequestFromFile('/api/issues/search', 'unresolved-unplanned-issues-by-action-plan.json',
+            { data: { resolved: 'false', planned: 'false' } });
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+            window.requestMessages().done(function () {
+              new IssueFilter({
+                el: '#issue-filter-widget',
+                query: 'resolved=false|planned=false',
+                distributionAxis: 'actionPlans'
+              });
+            });
+          });
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('#issue-filter-widget > table');
+      })
+
+      .then(function () {
+        // check count
+        test.assertElementCount('tr', 2);
+
+        // check order and values
+        test.assertSelectorContains('tr:nth-child(1)', '5877');
+        test.assertSelectorContains('tr:nth-child(2)', '5877');
+
+        // check links
+        test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false|planned=false"]');
+        test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|planned=false"]');
+
+        // check labels
+        test.assertSelectorContains('tr:nth-child(2)', 'unplanned');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
+
+
+casper.test.begin(testName('Unresolved Issues By Date'), 18, function (test) {
+  casper
+      .start(lib.buildUrl('issue-filter-widget'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequest('/api/l10n/index', '{}');
+        lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-date.json',
+            { data: { resolved: 'false' } });
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+            window.requestMessages().done(function () {
+              new IssueFilter({
+                el: '#issue-filter-widget',
+                query: 'resolved=false',
+                distributionAxis: 'createdAt'
+              });
+            });
+          });
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('#issue-filter-widget > table');
+      })
+
+      .then(function () {
+        // check count
+        test.assertElementCount('tr', 6);
+
+        // check order and values
+        test.assertSelectorContains('tr:nth-child(1)', '6851');
+        test.assertSelectorContains('tr:nth-child(2)', '72');
+        test.assertSelectorContains('tr:nth-child(3)', '64');
+        test.assertSelectorContains('tr:nth-child(4)', '1262');
+        test.assertSelectorContains('tr:nth-child(5)', '3729');
+        test.assertSelectorContains('tr:nth-child(6)', '1724');
+
+        // check links
+        test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false"]');
+        test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|createdAfter=2011-01-01|createdBefore=2011-12-31"]');
+        test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|createdAfter=2012-01-01|createdBefore=2012-12-31"]');
+        test.assertExists('tr:nth-child(4) a[href="/issues/search#resolved=false|createdAfter=2013-01-01|createdBefore=2013-12-31"]');
+        test.assertExists('tr:nth-child(5) a[href="/issues/search#resolved=false|createdAfter=2014-01-01|createdBefore=2014-12-31"]');
+        // do not check createdBefore value, because it is set dynamically to *now*
+        test.assertExists('tr:nth-child(6) a[href^="/issues/search#resolved=false|createdAfter=2015-01-01|createdBefore="]');
+
+        // check labels
+        test.assertSelectorContains('tr:nth-child(2)', 'January 1 2011 â€“ December 31 2011');
+        test.assertSelectorContains('tr:nth-child(3)', 'January 1 2012 â€“ December 31 2012');
+        test.assertSelectorContains('tr:nth-child(4)', 'January 1 2013 â€“ December 31 2013');
+        test.assertSelectorContains('tr:nth-child(5)', 'January 1 2014 â€“ December 31 2014');
+        // do not check label fully, because it is set dynamically using *now*
+        test.assertSelectorContains('tr:nth-child(6)', 'January 1 2015 â€“ ');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
+
+
+casper.test.begin(testName('Unresolved Issues on a Limited Period By Date'), 12, function (test) {
+  casper
+      .start(lib.buildUrl('issue-filter-widget'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequest('/api/l10n/index', '{}');
+        lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-date-limited.json',
+            { data: { resolved: 'false', createdAfter: '2015-02-16', createdBefore: '2015-02-18' } });
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+            window.requestMessages().done(function () {
+              new IssueFilter({
+                el: '#issue-filter-widget',
+                query: 'resolved=false|createdAfter=2015-02-16|createdBefore=2015-02-18',
+                distributionAxis: 'createdAt'
+              });
+            });
+          });
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('#issue-filter-widget > table');
+      })
+
+      .then(function () {
+        // check count
+        test.assertElementCount('tr', 4);
+
+        // check order and values
+        test.assertSelectorContains('tr:nth-child(1)', '6851');
+        test.assertSelectorContains('tr:nth-child(2)', '49');
+        test.assertSelectorContains('tr:nth-child(3)', '48');
+        test.assertSelectorContains('tr:nth-child(4)', '47');
+
+        // check links
+        test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false|createdAfter=2015-02-16|createdBefore=2015-02-18"]');
+        test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|createdAfter=2015-02-16|createdBefore=2015-02-17"]');
+        test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|createdAfter=2015-02-17|createdBefore=2015-02-18"]');
+        test.assertExists('tr:nth-child(4) a[href="/issues/search#resolved=false|createdAfter=2015-02-18|createdBefore=2015-02-19"]');
+
+        // check labels
+        test.assertSelectorContains('tr:nth-child(2)', 'February 16 2015');
+        test.assertSelectorContains('tr:nth-child(3)', 'February 17 2015');
+        test.assertSelectorContains('tr:nth-child(4)', 'February 18 2015');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
diff --git a/server/sonar-web/src/test/js/project-issue-filter-widget.js b/server/sonar-web/src/test/js/project-issue-filter-widget.js
new file mode 100644 (file)
index 0000000..25e69cd
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.
+ */
+/* globals casper: false */
+
+var lib = require('../lib'),
+    testName = lib.testName('Project Issue Filter Widget');
+
+
+lib.initMessages();
+lib.changeWorkingDirectory('project-issues-filter-widget');
+lib.configureCasper();
+
+
+casper.test.begin(testName('Unresolved Issues By Severity'), 13, function (test) {
+  casper
+      .start(lib.buildUrl('issue-filter-widget'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequest('/api/l10n/index', '{}');
+        lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-severity.json',
+            { data: { resolved: 'false' } });
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+            window.requestMessages().done(function () {
+              new IssueFilter({
+                el: '#issue-filter-widget',
+                query: 'resolved=false',
+                distributionAxis: 'severities',
+                componentUuid: '69e57151-be0d-4157-adff-c06741d88879',
+                componentKey: 'org.codehaus.sonar:sonar'
+              });
+            });
+          });
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('#issue-filter-widget > table');
+      })
+
+      .then(function () {
+        // check count
+        test.assertElementCount('tr', 6);
+
+        // check order and values
+        test.assertSelectorContains('tr:nth-child(1)', '6851');
+        test.assertSelectorContains('tr:nth-child(2)', '1');
+        test.assertSelectorContains('tr:nth-child(3)', '105');
+        test.assertSelectorContains('tr:nth-child(4)', '5027');
+        test.assertSelectorContains('tr:nth-child(5)', '540');
+        test.assertSelectorContains('tr:nth-child(6)', '1178');
+
+        // check links
+        test.assertExists('tr:nth-child(1) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false"]');
+        test.assertExists('tr:nth-child(2) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|severities=BLOCKER"]');
+        test.assertExists('tr:nth-child(3) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|severities=CRITICAL"]');
+        test.assertExists('tr:nth-child(4) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|severities=MAJOR"]');
+        test.assertExists('tr:nth-child(5) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|severities=MINOR"]');
+        test.assertExists('tr:nth-child(6) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|severities=INFO"]');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
+
+
+casper.test.begin(testName('Unresolved Issues By Date'), 18, function (test) {
+  casper
+      .start(lib.buildUrl('issue-filter-widget'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequest('/api/l10n/index', '{}');
+        lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-date.json',
+            { data: { resolved: 'false' } });
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+            window.requestMessages().done(function () {
+              new IssueFilter({
+                el: '#issue-filter-widget',
+                query: 'resolved=false',
+                distributionAxis: 'createdAt',
+                componentUuid: '69e57151-be0d-4157-adff-c06741d88879',
+                componentKey: 'org.codehaus.sonar:sonar'
+              });
+            });
+          });
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('#issue-filter-widget > table');
+      })
+
+      .then(function () {
+        // check count
+        test.assertElementCount('tr', 6);
+
+        // check order and values
+        test.assertSelectorContains('tr:nth-child(1)', '6851');
+        test.assertSelectorContains('tr:nth-child(2)', '72');
+        test.assertSelectorContains('tr:nth-child(3)', '64');
+        test.assertSelectorContains('tr:nth-child(4)', '1262');
+        test.assertSelectorContains('tr:nth-child(5)', '3729');
+        test.assertSelectorContains('tr:nth-child(6)', '1724');
+
+        // check links
+        test.assertExists('tr:nth-child(1) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false"]');
+        test.assertExists('tr:nth-child(2) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2011-01-01|createdBefore=2011-12-31"]');
+        test.assertExists('tr:nth-child(3) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2012-01-01|createdBefore=2012-12-31"]');
+        test.assertExists('tr:nth-child(4) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2013-01-01|createdBefore=2013-12-31"]');
+        test.assertExists('tr:nth-child(5) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2014-01-01|createdBefore=2014-12-31"]');
+        // do not check createdBefore value, because it is set dynamically to *now*
+        test.assertExists('tr:nth-child(6) a[href^="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2015-01-01|createdBefore="]');
+
+        // check labels
+        test.assertSelectorContains('tr:nth-child(2)', 'January 1 2011 â€“ December 31 2011');
+        test.assertSelectorContains('tr:nth-child(3)', 'January 1 2012 â€“ December 31 2012');
+        test.assertSelectorContains('tr:nth-child(4)', 'January 1 2013 â€“ December 31 2013');
+        test.assertSelectorContains('tr:nth-child(5)', 'January 1 2014 â€“ December 31 2014');
+        // do not check label fully, because it is set dynamically using *now*
+        test.assertSelectorContains('tr:nth-child(6)', 'January 1 2015 â€“ ');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
+
+
+casper.test.begin(testName('Unresolved Issues By Severity With Differential Period'), 13, function (test) {
+  casper
+      .start(lib.buildUrl('issue-filter-widget'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequest('/api/l10n/index', '{}');
+        lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-severity-with-differential-period.json',
+            { data: { resolved: 'false', createdAfter: '2014-12-09T17:12:38+0100' } });
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['/js/widgets/issue-filter.js'], function (IssueFilter) {
+            window.requestMessages().done(function () {
+              new IssueFilter({
+                el: '#issue-filter-widget',
+                query: 'resolved=false',
+                distributionAxis: 'severities',
+                periodDate: '2014-12-09T17:12:38+0100',
+                componentUuid: '69e57151-be0d-4157-adff-c06741d88879',
+                componentKey: 'org.codehaus.sonar:sonar'
+              });
+            });
+          });
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('#issue-filter-widget > table');
+      })
+
+      .then(function () {
+        // check count
+        test.assertElementCount('tr', 6);
+
+        // check order and values
+        test.assertSelectorContains('tr:nth-child(1)', '+549');
+        test.assertSelectorContains('tr:nth-child(2)', '+0');
+        test.assertSelectorContains('tr:nth-child(3)', '+59');
+        test.assertSelectorContains('tr:nth-child(4)', '+306');
+        test.assertSelectorContains('tr:nth-child(5)', '+135');
+        test.assertSelectorContains('tr:nth-child(6)', '+49');
+
+        // check links
+        test.assertExists('tr:nth-child(1) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2014-12-09T17%3A12%3A38%2B0100"]');
+        test.assertExists('tr:nth-child(2) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2014-12-09T17%3A12%3A38%2B0100|severities=BLOCKER"]');
+        test.assertExists('tr:nth-child(3) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2014-12-09T17%3A12%3A38%2B0100|severities=CRITICAL"]');
+        test.assertExists('tr:nth-child(4) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2014-12-09T17%3A12%3A38%2B0100|severities=MAJOR"]');
+        test.assertExists('tr:nth-child(5) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2014-12-09T17%3A12%3A38%2B0100|severities=MINOR"]');
+        test.assertExists('tr:nth-child(6) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false|createdAfter=2014-12-09T17%3A12%3A38%2B0100|severities=INFO"]');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/all-issues-by-resolution.json b/server/sonar-web/src/test/json/global-issues-filter-widget/all-issues-by-resolution.json
new file mode 100644 (file)
index 0000000..6751605
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  "total": 71571,
+  "p": 1,
+  "ps": 1,
+  "facets": [
+    {
+      "property": "resolutions",
+      "values": [
+        {
+          "val": "",
+          "count": 6851
+        },
+        {
+          "val": "FIXED",
+          "count": 47092
+        },
+        {
+          "val": "REMOVED",
+          "count": 16326
+        },
+        {
+          "val": "FALSE-POSITIVE",
+          "count": 752
+        },
+        {
+          "val": "WONTFIX",
+          "count": 550
+        }
+      ]
+    }
+  ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/all-issues-by-status.json b/server/sonar-web/src/test/json/global-issues-filter-widget/all-issues-by-status.json
new file mode 100644 (file)
index 0000000..99fe946
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  "total": 71571,
+  "p": 1,
+  "ps": 1,
+  "facets": [
+    {
+      "property": "statuses",
+      "values": [
+        {
+          "val": "CLOSED",
+          "count": 63413
+        },
+        {
+          "val": "CONFIRMED",
+          "count": 6609
+        },
+        {
+          "val": "RESOLVED",
+          "count": 1307
+        },
+        {
+          "val": "OPEN",
+          "count": 238
+        },
+        {
+          "val": "REOPENED",
+          "count": 4
+        }
+      ]
+    }
+  ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/red-issues-by-severity.json b/server/sonar-web/src/test/json/global-issues-filter-widget/red-issues-by-severity.json
new file mode 100644 (file)
index 0000000..f261766
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  "total": 6851,
+  "p": 1,
+  "ps": 1,
+  "facets": [
+    {
+      "property": "severities",
+      "values": [
+        {
+          "val": "MAJOR",
+          "count": 5027
+        },
+        {
+          "val": "INFO",
+          "count": 1178
+        },
+        {
+          "val": "MINOR",
+          "count": 540
+        },
+        {
+          "val": "CRITICAL",
+          "count": 105
+        },
+        {
+          "val": "BLOCKER",
+          "count": 1
+        }
+      ]
+    }
+  ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-action-plan.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-action-plan.json
new file mode 100644 (file)
index 0000000..7589fe0
--- /dev/null
@@ -0,0 +1,63 @@
+{
+  "total": 6851,
+  "p": 1,
+  "ps": 1,
+  "actionPlans": [
+    {
+      "key": "0cf48508-2fcd-4cb8-a50b-c5cd7c3decc0",
+      "name": "First Action Plan",
+      "status": "OPEN",
+      "project": "example:project",
+      "userLogin": "example.login",
+      "createdAt": "2014-04-03T12:28:05+0200",
+      "fCreatedAt": "Apr 3, 2014 12:28 PM",
+      "updatedAt": "2014-04-03T12:28:05+0200",
+      "fUpdatedAt": "Apr 3, 2014 12:28 PM"
+    },
+    {
+      "key": "1b9e7e52-ff58-40c1-80bf-f68429a3275e",
+      "name": "Second Action Plan",
+      "status": "OPEN",
+      "project": "example:project",
+      "userLogin": "example.login",
+      "createdAt": "2014-04-03T12:28:05+0200",
+      "fCreatedAt": "Apr 3, 2014 12:28 PM",
+      "updatedAt": "2014-04-03T12:28:05+0200",
+      "fUpdatedAt": "Apr 3, 2014 12:28 PM"
+    },
+    {
+      "key": "8c1d5d01-948e-4670-a0d9-17c512979486",
+      "name": "Third Action Plan",
+      "status": "OPEN",
+      "project": "example:project",
+      "userLogin": "example.login",
+      "createdAt": "2014-04-03T12:28:05+0200",
+      "fCreatedAt": "Apr 3, 2014 12:28 PM",
+      "updatedAt": "2014-04-03T12:28:05+0200",
+      "fUpdatedAt": "Apr 3, 2014 12:28 PM"
+    }
+  ],
+  "facets": [
+    {
+      "property": "actionPlans",
+      "values": [
+        {
+          "val": "",
+          "count": 5877
+        },
+        {
+          "val": "0cf48508-2fcd-4cb8-a50b-c5cd7c3decc0",
+          "count": 532
+        },
+        {
+          "val": "1b9e7e52-ff58-40c1-80bf-f68429a3275e",
+          "count": 56
+        },
+        {
+          "val": "8c1d5d01-948e-4670-a0d9-17c512979486",
+          "count": 52
+        }
+      ]
+    }
+  ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-assignee.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-assignee.json
new file mode 100644 (file)
index 0000000..3503278
--- /dev/null
@@ -0,0 +1,48 @@
+{
+  "total": 6851,
+  "p": 1,
+  "ps": 1,
+  "users": [
+    {
+      "login": "second.user",
+      "name": "Second User",
+      "active": true,
+      "email": "second.user@example.com"
+    },
+    {
+      "login": "third.user",
+      "name": "Third User",
+      "active": true,
+      "email": "third.user@example  .com"
+    },
+    {
+      "login": "first.user",
+      "name": "First User",
+      "active": true,
+      "email": "first.user@example.com"
+    }
+  ],
+  "facets": [
+    {
+      "property": "assignees",
+      "values": [
+        {
+          "val": "",
+          "count": 4134
+        },
+        {
+          "val": "first.user",
+          "count": 698
+        },
+        {
+          "val": "second.user",
+          "count": 504
+        },
+        {
+          "val": "third.user",
+          "count": 426
+        }
+      ]
+    }
+  ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-date-limited.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-date-limited.json
new file mode 100644 (file)
index 0000000..5c2f018
--- /dev/null
@@ -0,0 +1,24 @@
+{
+  "total": 6851,
+  "p": 1,
+  "ps": 1,
+  "facets": [
+    {
+      "property": "createdAt",
+      "values": [
+        {
+          "val": "2015-02-16T01:00:00+0000",
+          "count": 49
+        },
+        {
+          "val": "2015-02-17T01:00:00+0000",
+          "count": 48
+        },
+        {
+          "val": "2015-02-18T01:00:00+0000",
+          "count": 47
+        }
+      ]
+    }
+  ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-date.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-date.json
new file mode 100644 (file)
index 0000000..54153d9
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  "total": 6851,
+  "p": 1,
+  "ps": 1,
+  "facets": [
+    {
+      "property": "createdAt",
+      "values": [
+        {
+          "val": "2011-01-01T01:00:00+0000",
+          "count": 72
+        },
+        {
+          "val": "2012-01-01T01:00:00+0000",
+          "count": 64
+        },
+        {
+          "val": "2013-01-01T01:00:00+0000",
+          "count": 1262
+        },
+        {
+          "val": "2014-01-01T01:00:00+0000",
+          "count": 3729
+        },
+        {
+          "val": "2015-01-01T01:00:00+0000",
+          "count": 1724
+        }
+      ]
+    }
+  ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-language.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-language.json
new file mode 100644 (file)
index 0000000..de5e4c9
--- /dev/null
@@ -0,0 +1,46 @@
+{
+  "total": 6851,
+  "p": 1,
+  "ps": 1,
+  "languages": [
+    {
+      "key": "py",
+      "name": "Python"
+    },
+    {
+      "key": "js",
+      "name": "JavaScript"
+    },
+    {
+      "key": "php",
+      "name": "PHP"
+    },
+    {
+      "key": "java",
+      "name": "Java"
+    }
+  ],
+  "facets": [
+    {
+      "property": "languages",
+      "values": [
+        {
+          "val": "java",
+          "count": 6336
+        },
+        {
+          "val": "py",
+          "count": 444
+        },
+        {
+          "val": "php",
+          "count": 22
+        },
+        {
+          "val": "js",
+          "count": 15
+        }
+      ]
+    }
+  ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-project.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-project.json
new file mode 100644 (file)
index 0000000..e53991f
--- /dev/null
@@ -0,0 +1,62 @@
+{
+  "total": 2598,
+  "p": 1,
+  "ps": 1,
+  "projects": [
+    {
+      "uuid": "5eab015a-1f76-4ba4-bd89-bf547132d673",
+      "key": "org.codehaus.sonar-plugins.javascript:javascript",
+      "id": 10159,
+      "qualifier": "TRK",
+      "name": "JavaScript",
+      "longName": "JavaScript"
+    },
+    {
+      "uuid": "c156940b-e3ec-43f6-9589-e3b75aa9ca32",
+      "key": "org.codehaus.sonar-plugins.python:python",
+      "id": 11752,
+      "qualifier": "TRK",
+      "name": "Python",
+      "longName": "Python"
+    },
+    {
+      "uuid": "dd7c3556-ce3f-42d0-a348-914a582dc944",
+      "key": "org.codehaus.sonar-plugins.java:java",
+      "id": 13265,
+      "qualifier": "TRK",
+      "name": "SonarQube Java",
+      "longName": "SonarQube Java"
+    },
+    {
+      "uuid": "69e57151-be0d-4157-adff-c06741d88879",
+      "key": "org.codehaus.sonar:sonar",
+      "id": 2865,
+      "qualifier": "TRK",
+      "name": "SonarQube",
+      "longName": "SonarQube"
+    }
+  ],
+  "facets": [
+    {
+      "property": "projectUuids",
+      "values": [
+        {
+          "val": "69e57151-be0d-4157-adff-c06741d88879",
+          "count": 1766
+        },
+        {
+          "val": "dd7c3556-ce3f-42d0-a348-914a582dc944",
+          "count": 442
+        },
+        {
+          "val": "5eab015a-1f76-4ba4-bd89-bf547132d673",
+          "count": 283
+        },
+        {
+          "val": "c156940b-e3ec-43f6-9589-e3b75aa9ca32",
+          "count": 107
+        }
+      ]
+    }
+  ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-resolution.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-resolution.json
new file mode 100644 (file)
index 0000000..1469206
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  "total": 6851,
+  "p": 1,
+  "ps": 1,
+  "facets": [
+    {
+      "property": "resolutions",
+      "values": [
+        {
+          "val": "",
+          "count": 6851
+        },
+        {
+          "val": "FIXED",
+          "count": 47092
+        },
+        {
+          "val": "REMOVED",
+          "count": 16326
+        },
+        {
+          "val": "FALSE-POSITIVE",
+          "count": 752
+        },
+        {
+          "val": "WONTFIX",
+          "count": 550
+        }
+      ]
+    }
+  ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-rule.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-rule.json
new file mode 100644 (file)
index 0000000..aa70a9b
--- /dev/null
@@ -0,0 +1,186 @@
+{
+  "total": 6851,
+  "p": 1,
+  "ps": 1,
+  "rules": [
+    {
+      "key": "squid:S1698",
+      "name": "Objects should be compared with \"equals()\"",
+      "lang": "java",
+      "desc": "<p>Using the equality (<code>==</code>) and inequality (<code>!=</code>) operators to compare two objects does not check to see if they have the same values. Rather it checks to see if both object references point to exactly the same object in memory. The vast majority of the time, this is not what you want to do. Use the .equals() method to compare the values of two objects or to compare a string object to a string literal.</p>\n\n<h2>Noncompliant Code Sample</h2>\n<pre>\nString str1 = \"blue\";\nString str2 = \"blue\";\nString str3 = str1;\n\nif (str1 == str2)\n{\n  System.out.println(\"they're both 'blue'\"); // this doesn't print because the objects are different\n}\n\nif (str1 == \"blue\")\n{\n  System.out.println(\"they're both 'blue'\"); // this doesn't print because the objects are different\n}\n\nif (str1 == str3)\n{\n  System.out.println(\"they're the same object\"); // this prints\n}\n</pre>\n\n<h2>Compliant Solution</h2>\n<pre>\nString str1 = \"blue\";\nString str2 = \"blue\";\nString str3 = str1;\n\nif (str1.equals(str2))\n{\n  System.out.println(\"they're both 'blue'\"); // this prints\n}\n\nif (str1.equals(\"blue\"))\n{\n  System.out.println(\"they're both 'blue'\"); // this prints\n}\n\nif (str1 == str3)\n{\n  System.out.println(\"they're the same object\"); // this still prints, but it's probably not what you meant to do\n}\n</pre>\n\n<h2>Exception</h2>\nComparing two instances of the <code>Class</code> object will not raise an issue.\n<pre>\nClass c;\nif(c == Integer.class) { //No issue raised\n}\n</pre>\n\n<h2>See</h2>\n    <ul>\n      <li><a href=\"http://cwe.mitre.org/data/definitions/595.html\">MITRE, CWE-595</a> - Comparison of Object References Instead of Object Contents</li>\n    </ul>",
+      "status": "READY",
+      "langName": "Java"
+    },
+    {
+      "key": "squid:AstNode_SSLR_class_should_not_be_used",
+      "name": "AstNode SSLR class should not be used",
+      "lang": "java",
+      "desc": "Once strongly typed AST is in place on a language plugin, the AstNode class should not be used anymore. ",
+      "status": "READY",
+      "langName": "Java"
+    },
+    {
+      "key": "squid:IndentationCheck",
+      "name": "Source code should be correctly indented",
+      "lang": "java",
+      "desc": "<p>\nProper indentation is a simple and effective way to improve the code's readability.\nConsistent indentation among developers also reduces the differences that are committed to source control systems, making code reviews easier.\n</p>\n\n<p>The following code illustrates this rule with an indentation level of 2:</p>\n\n<pre>\nclass Foo {\n  public int a; // Compliant\npublic int b;   // Non-Compliant\n}\n</pre>",
+      "status": "READY",
+      "langName": "Java"
+    },
+    {
+      "key": "squid:S1161",
+      "name": "\"@Override\" annotation should be used on any method overriding (since Java 5) or implementing (since Java 6) another one",
+      "lang": "java",
+      "desc": "<p>Using the <code>@Override</code> annotation is useful for two reasons :</p>\n<ul>\n  <li>It elicits a warning from the compiler if the annotated method doesn't actually override anything, as in the case of a misspelling.</li>\n  <li>It improves the readability of the source code by making it obvious that methods are overridden.</li>\n</ul>\n<h2>Noncompliant Code Example</h2>\n<pre>\nclass ParentClass {\n  public boolean doSomething(){...}\n}\nclass FirstChildClass extends ParentClass {\n  public boolean doSomething(){...}  //Non-Compliant\n}\n</pre>\n\n<h2>Compliant Solution</h2>\n<pre>\nclass ParentClass {\n  public boolean doSomething(){...}\n}\nclass FirstChildClass extends ParentClass {\n  @Override\n  public boolean doSomething(){...}  //Compliant\n}\n</pre>",
+      "status": "READY",
+      "langName": "Java"
+    },
+    {
+      "key": "common-java:DuplicatedBlocks",
+      "name": "Duplicated blocks",
+      "lang": "java",
+      "desc": "<p>An issue is created on a file as soon as there is a block of duplicated code on this file. It gives the number of blocks in the file.</p>",
+      "status": "READY",
+      "langName": "Java"
+    },
+    {
+      "key": "squid:S1192",
+      "name": "String literals should not be duplicated",
+      "lang": "java",
+      "desc": "<p>\n  Duplicated string literals make the process of refactoring error-prone, since you must be sure to update all occurrences.\n  On the other hand, constants can be referenced from many places, but only need to be updated in a single place.\n</p>\n\n<h2>Non Compliant Code Example</h2>\n\n<pre>\npublic void run() {\n  prepare(\"action1\");                              // Non-Compliant - \"action1\" is duplicated 3 times\n  execute(\"action1\");\n  release(\"action1\");\n}\n\n@SuppressWarning(\"all\")                            // Compliant - annotations are excluded\nprivate void method1() { /* ... */ }\n@SuppressWarning(\"all\")\nprivate void method2() { /* ... */ }\n\npublic String method3(String a) {\n  System.out.println(\"'\" + a + \"'\");               // Compliant - literal \"'\" has less than 5 characters and is excluded\n  return \"\";                                       // Compliant - literal \"\" has less than 5 characters and is excluded\n}\n</pre>\n\n<h2>Compliant Code Example</h2>\n\n<pre>\nprivate static final String ACTION_1 = \"action1\";  // Compliant\n\npublic void run() {\n  prepare(ACTION_1);                               // Compliant\n  execute(ACTION_1);\n  release(ACTION_1);\n}\n</pre>\n\n<h2>Exceptions</h2>\n<p>To prevent generating some false-positives, literals having less than 5 characters are excluded.</p>",
+      "status": "READY",
+      "langName": "Java"
+    },
+    {
+      "key": "squid:MethodCyclomaticComplexity",
+      "name": "Methods should not be too complex",
+      "lang": "java",
+      "desc": "<p>The Cyclomatic Complexity is measured by the number of\n\t(&amp;&amp;, ||) operators and (if, while, do, for, ?:, catch, switch,\n\tcase, return, throw) statements in the body of a class plus one for\n\teach constructor, method (but not getter/setter), static initializer,\n\tor instance initializer in the class. The last return statement in\n\tmethod, if exists, is not taken into account.</p>\n<p>\n\tEven when the Cyclomatic Complexity of a class is very high, this\n\tcomplexity might be well distributed among all methods. Nevertheless,\n\tmost of the time, a very complex class is a class which breaks the <a\n\t\thref=\"http://en.wikipedia.org/wiki/Single_responsibility_principle\">Single\n\t\tResponsibility Principle</a> and which should be re-factored to be split\n\tin several classes.\n</p>",
+      "status": "READY",
+      "langName": "Java"
+    },
+    {
+      "key": "squid:S1135",
+      "name": "TODO tags should be handled",
+      "lang": "java",
+      "desc": "<p>\n<code>TODO</code> tags are commonly used to mark places where some more code is required, but which the developer wants to implement later.\nSometimes the developer will not have the time or will simply forget to get back to that tag.\nThis rule is meant to track those tags, and ensure that they do not go unnoticed.\n</p>\n\n<p>The following code illustrates this rule:</p>\n\n<pre>\nvoid doSomething() {\n  // TODO\n}\n</pre>",
+      "status": "READY",
+      "langName": "Java"
+    },
+    {
+      "key": "common-java:InsufficientBranchCoverage",
+      "name": "Insufficient branch coverage by unit tests",
+      "lang": "java",
+      "desc": "<p>An issue is created on a file as soon as the branch coverage on this file is less than the required threshold.It gives the number of branches to be covered in order to reach the required threshold.</p>",
+      "status": "READY",
+      "langName": "Java"
+    },
+    {
+      "key": "squid:S00115",
+      "name": "Constant names should comply with a naming convention",
+      "lang": "java",
+      "desc": "<p>\nSharing some naming conventions is a key point to make it possible for a team to efficiently collaborate. This rule allows to check that all constant names match a provided regular expression.\n</p>\n\n<p>\nThe following code snippet illustrates this rule when the regular expression value is \"^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$\":\n</p>\n<pre>\npublic class MyClass {\n  public static final int first = 1; // Non-Compliant\n  public static final int SECOND = 2; // Compliant\n}\n\npublic enum MyEnum {\n  first, // Non-Compliant\n  SECOND; // Compliant\n}\n</pre>",
+      "status": "READY",
+      "langName": "Java"
+    },
+    {
+      "key": "squid:S1134",
+      "name": "FIXME tags should be handled",
+      "lang": "java",
+      "desc": "<p>\n<code>FIXME</code> tags are commonly used to mark places where a bug is suspected, but which the developer wants to deal with later.\nSometimes the developer will not have the time or will simply forget to get back to that tag.\nThis rule is meant to track those tags, and ensure that they do not go unnoticed.\n</p>\n\n<p>The following code illustrates this rule:</p>\n\n<pre>\nint divide(int numerator, int denominator) {\n  return numerator / denominator;              // FIXME denominator = 0, Non-Compliant\n}\n</pre>",
+      "status": "READY",
+      "langName": "Java"
+    },
+    {
+      "key": "squid:S1133",
+      "name": "Deprecated code should be removed eventually",
+      "lang": "java",
+      "desc": "<p>\nThis rule is meant to be used as a way to track code which is marked as being deprecated.\nDeprecated code should eventually be removed.\n</p>\n\n<p>\nThe following code illustrates this rule:\n</p>\n\n<pre>\nclass Foo {\n  /**\n    * @deprecated\n    */\n  public void foo() {    // Non-Compliant\n  }\n\n  @Deprecated            // Non-Compliant\n  public void bar() {\n  }\n\n  public void baz() {    // Compliant\n  }\n}\n</pre>",
+      "status": "READY",
+      "langName": "Java"
+    },
+    {
+      "key": "squid:CallToDeprecatedMethod",
+      "name": "Avoid use of deprecated method",
+      "lang": "java",
+      "desc": "<p>Once deprecated, a method should no longer be used as it means\n\tthat the method might be removed sooner or later.</p>",
+      "status": "READY",
+      "langName": "Java"
+    },
+    {
+      "key": "squid:S1228",
+      "name": "Packages should have a javadoc file 'package-info.java'",
+      "lang": "java",
+      "desc": "<p>Each package in a Java project should include a <code>package-info.java</code> file. The purpose of this file is to document the Java package using javadoc and declare package annotations.</p>\n\n<h2>Compliant Solution</h2>\n<pre>\n/**\n* This package has non null parameters and is documented.\n**/\n@ParametersAreNonnullByDefault\npackage org.foo.bar;\n</pre>",
+      "status": "READY",
+      "langName": "Java"
+    }
+  ],
+  "facets": [
+    {
+      "property": "rules",
+      "values": [
+        {
+          "val": "squid:S1161",
+          "count": 879
+        },
+        {
+          "val": "squid:S1135",
+          "count": 571
+        },
+        {
+          "val": "squid:S1133",
+          "count": 558
+        },
+        {
+          "val": "common-java:InsufficientBranchCoverage",
+          "count": 550
+        },
+        {
+          "val": "common-java:DuplicatedBlocks",
+          "count": 408
+        },
+        {
+          "val": "squid:AstNode_SSLR_class_should_not_be_used",
+          "count": 265
+        },
+        {
+          "val": "squid:IndentationCheck",
+          "count": 264
+        },
+        {
+          "val": "squid:CallToDeprecatedMethod",
+          "count": 237
+        },
+        {
+          "val": "squid:MethodCyclomaticComplexity",
+          "count": 233
+        },
+        {
+          "val": "squid:S00115",
+          "count": 212
+        },
+        {
+          "val": "resharper-cs:RedundantUsingDirective",
+          "count": 175
+        },
+        {
+          "val": "squid:S1228",
+          "count": 174
+        },
+        {
+          "val": "squid:S1698",
+          "count": 139
+        },
+        {
+          "val": "squid:S1134",
+          "count": 113
+        },
+        {
+          "val": "squid:S1192",
+          "count": 111
+        }
+      ]
+    }
+  ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-severity.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-severity.json
new file mode 100644 (file)
index 0000000..f261766
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  "total": 6851,
+  "p": 1,
+  "ps": 1,
+  "facets": [
+    {
+      "property": "severities",
+      "values": [
+        {
+          "val": "MAJOR",
+          "count": 5027
+        },
+        {
+          "val": "INFO",
+          "count": 1178
+        },
+        {
+          "val": "MINOR",
+          "count": 540
+        },
+        {
+          "val": "CRITICAL",
+          "count": 105
+        },
+        {
+          "val": "BLOCKER",
+          "count": 1
+        }
+      ]
+    }
+  ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-unassigned-issues-by-assignee.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-unassigned-issues-by-assignee.json
new file mode 100644 (file)
index 0000000..eec6932
--- /dev/null
@@ -0,0 +1,48 @@
+{
+  "total": 4134,
+  "p": 1,
+  "ps": 1,
+  "users": [
+    {
+      "login": "second.user",
+      "name": "Second User",
+      "active": true,
+      "email": "second.user@example.com"
+    },
+    {
+      "login": "third.user",
+      "name": "Third User",
+      "active": true,
+      "email": "third.user@example  .com"
+    },
+    {
+      "login": "first.user",
+      "name": "First User",
+      "active": true,
+      "email": "first.user@example.com"
+    }
+  ],
+  "facets": [
+    {
+      "property": "assignees",
+      "values": [
+        {
+          "val": "",
+          "count": 4134
+        },
+        {
+          "val": "first.user",
+          "count": 698
+        },
+        {
+          "val": "second.user",
+          "count": 504
+        },
+        {
+          "val": "third.user",
+          "count": 426
+        }
+      ]
+    }
+  ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-unplanned-issues-by-action-plan.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-unplanned-issues-by-action-plan.json
new file mode 100644 (file)
index 0000000..94eba94
--- /dev/null
@@ -0,0 +1,63 @@
+{
+  "total": 5877,
+  "p": 1,
+  "ps": 1,
+  "actionPlans": [
+    {
+      "key": "0cf48508-2fcd-4cb8-a50b-c5cd7c3decc0",
+      "name": "First Action Plan",
+      "status": "OPEN",
+      "project": "example:project",
+      "userLogin": "example.login",
+      "createdAt": "2014-04-03T12:28:05+0200",
+      "fCreatedAt": "Apr 3, 2014 12:28 PM",
+      "updatedAt": "2014-04-03T12:28:05+0200",
+      "fUpdatedAt": "Apr 3, 2014 12:28 PM"
+    },
+    {
+      "key": "1b9e7e52-ff58-40c1-80bf-f68429a3275e",
+      "name": "Second Action Plan",
+      "status": "OPEN",
+      "project": "example:project",
+      "userLogin": "example.login",
+      "createdAt": "2014-04-03T12:28:05+0200",
+      "fCreatedAt": "Apr 3, 2014 12:28 PM",
+      "updatedAt": "2014-04-03T12:28:05+0200",
+      "fUpdatedAt": "Apr 3, 2014 12:28 PM"
+    },
+    {
+      "key": "8c1d5d01-948e-4670-a0d9-17c512979486",
+      "name": "Third Action Plan",
+      "status": "OPEN",
+      "project": "example:project",
+      "userLogin": "example.login",
+      "createdAt": "2014-04-03T12:28:05+0200",
+      "fCreatedAt": "Apr 3, 2014 12:28 PM",
+      "updatedAt": "2014-04-03T12:28:05+0200",
+      "fUpdatedAt": "Apr 3, 2014 12:28 PM"
+    }
+  ],
+  "facets": [
+    {
+      "property": "actionPlans",
+      "values": [
+        {
+          "val": "",
+          "count": 5877
+        },
+        {
+          "val": "0cf48508-2fcd-4cb8-a50b-c5cd7c3decc0",
+          "count": 532
+        },
+        {
+          "val": "1b9e7e52-ff58-40c1-80bf-f68429a3275e",
+          "count": 56
+        },
+        {
+          "val": "8c1d5d01-948e-4670-a0d9-17c512979486",
+          "count": 52
+        }
+      ]
+    }
+  ]
+}
diff --git a/server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-date.json b/server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-date.json
new file mode 100644 (file)
index 0000000..54153d9
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  "total": 6851,
+  "p": 1,
+  "ps": 1,
+  "facets": [
+    {
+      "property": "createdAt",
+      "values": [
+        {
+          "val": "2011-01-01T01:00:00+0000",
+          "count": 72
+        },
+        {
+          "val": "2012-01-01T01:00:00+0000",
+          "count": 64
+        },
+        {
+          "val": "2013-01-01T01:00:00+0000",
+          "count": 1262
+        },
+        {
+          "val": "2014-01-01T01:00:00+0000",
+          "count": 3729
+        },
+        {
+          "val": "2015-01-01T01:00:00+0000",
+          "count": 1724
+        }
+      ]
+    }
+  ]
+}
diff --git a/server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-severity-with-differential-period.json b/server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-severity-with-differential-period.json
new file mode 100644 (file)
index 0000000..afa5ed4
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  "total": 549,
+  "p": 1,
+  "ps": 1,
+  "facets": [
+    {
+      "property": "severities",
+      "values": [
+        {
+          "val": "MAJOR",
+          "count": 306
+        },
+        {
+          "val": "MINOR",
+          "count": 135
+        },
+        {
+          "val": "CRITICAL",
+          "count": 59
+        },
+        {
+          "val": "INFO",
+          "count": 49
+        },
+        {
+          "val": "BLOCKER",
+          "count": 0
+        }
+      ]
+    }
+  ]
+}
diff --git a/server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-severity.json b/server/sonar-web/src/test/json/project-issues-filter-widget/unresolved-issues-by-severity.json
new file mode 100644 (file)
index 0000000..f261766
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  "total": 6851,
+  "p": 1,
+  "ps": 1,
+  "facets": [
+    {
+      "property": "severities",
+      "values": [
+        {
+          "val": "MAJOR",
+          "count": 5027
+        },
+        {
+          "val": "INFO",
+          "count": 1178
+        },
+        {
+          "val": "MINOR",
+          "count": 540
+        },
+        {
+          "val": "CRITICAL",
+          "count": 105
+        },
+        {
+          "val": "BLOCKER",
+          "count": 1
+        }
+      ]
+    }
+  ]
+}
index ed8b46791d4758df7aad337d2bcc0c6da5093d90..82204cdacfe3304fc0b190beb7fcf3cde530f959 100644 (file)
@@ -168,7 +168,6 @@ exports.assertLinkHref = function assertElementCount(selector, href, message) {
 
 exports.sendCoverage = function () {
   return casper.evaluate(function () {
-    console.log(Object.keys(window.__coverage__));
     jQuery.ajax({
       type: 'POST',
       url: '/coverage/client',
diff --git a/server/sonar-web/src/test/views/issue-filter-widget.jade b/server/sonar-web/src/test/views/issue-filter-widget.jade
new file mode 100644 (file)
index 0000000..97a22c3
--- /dev/null
@@ -0,0 +1,9 @@
+extends layouts/main
+
+block header
+  script(src='../js/require.js')
+  script.
+    requirejs.config({ baseUrl: '/js' });
+
+block body
+  #issue-filter-widget