Fix counting of selected and filtered check results

When all results are selected then the count should not render
"filtered". To accomplish this we are passing all the runs and results
into the results component and let it do the filtering itself. Then
it can compare, if what is shown is less than all there is.

Change-Id: I13a40c3030a6ed07ac561d86d5d417553290e0fd
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-results.ts b/polygerrit-ui/app/elements/checks/gr-checks-results.ts
index da596fe..feecd66 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-results.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-results.ts
@@ -60,7 +60,7 @@
 import {toggleClass, whenVisible} from '../../utils/dom-util';
 import {durationString} from '../../utils/date-util';
 import {charsOnly, pluralize} from '../../utils/string-util';
-import {fireRunSelectionReset, isSelected} from './gr-checks-util';
+import {fireRunSelectionReset, isAttemptSelected} from './gr-checks-util';
 import {ChecksTabState} from '../../types/events';
 import {ConfigInfo, PatchSetNumber} from '../../types/common';
 import {latestPatchNum$} from '../../services/change/change-model';
@@ -473,9 +473,17 @@
   @internalProperty()
   filterRegExp = new RegExp('');
 
+  /** All runs. Shown should only the selected/filtered ones. */
   @property()
   runs: CheckRun[] = [];
 
+  /**
+   * Check names of runs that are selected in the runs panel. When this array
+   * is empty, then no run is selected and all runs should be shown.
+   */
+  @property()
+  selectedRuns: string[] = [];
+
   @property()
   actions: Action[] = [];
 
@@ -491,14 +499,6 @@
   @property()
   latestPatchsetNumber: PatchSetNumber | undefined = undefined;
 
-  /**
-   * How many runs are selected in the runs panel?
-   * If 0, then the `runs` property contains all the runs there are.
-   * If >0, then it only contains the data of certain selected runs.
-   */
-  @property()
-  selectedRunsCount = 0;
-
   /** Maps checkName to selected attempt number. `undefined` means `latest`. */
   @property()
   selectedAttempts: Map<string, number | undefined> = new Map<
@@ -767,11 +767,19 @@
     });
   }
 
-  renderFilter() {
-    const runs = this.runs.filter(run =>
-      isSelected(this.selectedAttempts, run)
+  isRunSelected(run: {checkName: string}) {
+    return (
+      this.selectedRuns.length === 0 ||
+      this.selectedRuns.includes(run.checkName)
     );
-    if (this.selectedRunsCount === 0 && allResults(runs).length <= 3) {
+  }
+
+  renderFilter() {
+    const runs = this.runs.filter(
+      run =>
+        this.isRunSelected(run) && isAttemptSelected(this.selectedAttempts, run)
+    );
+    if (this.selectedRuns.length === 0 && allResults(runs).length <= 3) {
       if (this.filterRegExp.source.length > 0) {
         this.filterRegExp = new RegExp('');
       }
@@ -791,7 +799,7 @@
   }
 
   renderSelectionFilter() {
-    const count = this.selectedRunsCount;
+    const count = this.selectedRuns.length;
     if (count === 0) return;
     return html`
       <iron-icon class="filter" icon="gr-icons:filter"></iron-icon>
@@ -814,20 +822,23 @@
 
   renderSection(category: Category | 'SUCCESS') {
     const catString = category.toString().toLowerCase();
-    let runs = this.runs.filter(run => isSelected(this.selectedAttempts, run));
+    let allRuns = this.runs.filter(run =>
+      isAttemptSelected(this.selectedAttempts, run)
+    );
     if (category === 'SUCCESS') {
-      runs = runs.filter(hasCompletedWithoutResults);
+      allRuns = allRuns.filter(hasCompletedWithoutResults);
     } else {
-      runs = runs.filter(r => hasResultsOf(r, category));
+      allRuns = allRuns.filter(r => hasResultsOf(r, category));
     }
-    const all = runs.reduce(
-      (allResults: RunResult[], run) => [
-        ...allResults,
+    const all = allRuns.reduce(
+      (results: RunResult[], run) => [
+        ...results,
         ...this.computeRunResults(category, run),
       ],
       []
     );
-    const filtered = all.filter(
+    const selected = all.filter(result => this.isRunSelected(result));
+    const filtered = selected.filter(
       result =>
         this.filterRegExp.test(result.checkName) ||
         this.filterRegExp.test(result.summary)
@@ -835,7 +846,7 @@
     let expanded = this.isSectionExpanded.get(category);
     const expandedByUser = this.isSectionExpandedByUser.get(category) ?? false;
     if (!expandedByUser || expanded === undefined) {
-      expanded = all.length > 0;
+      expanded = selected.length > 0;
       this.isSectionExpanded.set(category, expanded);
     }
     const expandedClass = expanded ? 'expanded' : 'collapsed';
@@ -852,22 +863,28 @@
             class="statusIcon ${catString}"
           ></iron-icon>
           <span class="title">${catString}</span>
-          <span class="count">${this.renderCount(all, filtered)}</span>
+          <span class="count"
+            >${this.renderCount(all, selected, filtered)}</span
+          >
         </h3>
-        ${this.renderResults(all, filtered)}
+        ${this.renderResults(all, selected, filtered)}
       </div>
     `;
   }
 
-  renderResults(all: RunResult[], filtered: RunResult[]) {
-    if (all.length === 0 && this.selectedRunsCount > 0) {
+  renderResults(
+    all: RunResult[],
+    selected: RunResult[],
+    filtered: RunResult[]
+  ) {
+    if (all.length === 0) {
+      return html`<div class="noResultsMessage">No results</div>`;
+    }
+    if (selected.length === 0) {
       return html`<div class="noResultsMessage">
         No results for this filtered view
       </div>`;
     }
-    if (all.length === 0) {
-      return html`<div class="noResultsMessage">No results</div>`;
-    }
     if (filtered.length === 0) {
       return html`<div class="noResultsMessage">
         No results match the regular expression
@@ -899,15 +916,14 @@
     `;
   }
 
-  renderCount(all: RunResult[], filtered: RunResult[]) {
-    if (this.selectedRunsCount > 0) {
-      return html`<span class="filtered"> - filtered</span>`;
-    }
+  renderCount(all: RunResult[], selected: RunResult[], filtered: RunResult[]) {
     if (all.length === filtered.length) {
       return html`(${all.length})`;
-    } else {
-      return html`(${filtered.length} of ${all.length})`;
     }
+    if (all.length !== selected.length) {
+      return html`<span class="filtered"> - filtered</span>`;
+    }
+    return html`(${filtered.length} of ${all.length})`;
   }
 
   toggleExpanded(category: Category | 'SUCCESS') {
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-tab.ts b/polygerrit-ui/app/elements/checks/gr-checks-tab.ts
index beec4c8..acabb22 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-tab.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-tab.ts
@@ -108,11 +108,6 @@
   }
 
   render() {
-    const filteredRuns = this.runs.filter(
-      r =>
-        this.selectedRuns.length === 0 ||
-        this.selectedRuns.includes(r.checkName)
-    );
     return html`
       <div class="container">
         <gr-checks-runs
@@ -127,8 +122,8 @@
         <gr-checks-results
           class="results"
           .tabState="${this.tabState}"
-          .runs="${filteredRuns}"
-          .selectedRunsCount="${this.selectedRuns.length}"
+          .runs="${this.runs}"
+          .selectedRuns="${this.selectedRuns}"
           .selectedAttempts="${this.selectedAttempts}"
           @run-selected="${this.handleRunSelected}"
         ></gr-checks-results>
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-util.ts b/polygerrit-ui/app/elements/checks/gr-checks-util.ts
index 9a68e5b..05a87a4 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-util.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-util.ts
@@ -76,7 +76,7 @@
   );
 }
 
-export function isSelected(
+export function isAttemptSelected(
   selectedAttempts: Map<string, number | undefined>,
   run: CheckRun
 ) {