Merge "Fix counting of selected and filtered check results"
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
 ) {