Sync dashboard query tests with current UI

Recent gr-dashboard-view changes have ignored the requirement to keep
the Java tests synchronized with the query definitions. This change
updates the javascript comment to point at the new location of the Java
tests, adds tests for the new "Has unpublished drafts" section, and
updates the tests for the "Recently closed" section to account for the
recent inclusion of the "cc:me" term.

Change-Id: Id35178223b171a4da008a291b74989bff6b35217
diff --git a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index 82c9147..4bcdf94 100644
--- a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -74,6 +74,7 @@
 import com.google.gerrit.index.Schema;
 import com.google.gerrit.lifecycle.LifecycleManager;
 import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Account.Id;
 import com.google.gerrit.reviewdb.client.Branch;
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.Patch;
@@ -198,6 +199,7 @@
   // These queries must be kept in sync with PolyGerrit:
   // polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
 
+  protected static final String DASHBOARD_HAS_UNPUBLISHED_DRAFTS_QUERY = "has:draft";
   protected static final String DASHBOARD_WORK_IN_PROGRESS_QUERY = "is:open owner:${user} is:wip";
   protected static final String DASHBOARD_OUTGOING_QUERY =
       "is:open owner:${user} -is:wip -is:ignored";
@@ -205,7 +207,8 @@
       "is:open -owner:${user} -is:wip -is:ignored (reviewer:${user} OR assignee:${user})";
   protected static final String DASHBOARD_RECENTLY_CLOSED_QUERY =
       "is:closed -is:ignored (-is:wip OR owner:self) "
-          + "(owner:${user} OR reviewer:${user} OR assignee:${user})";
+          + "(owner:${user} OR reviewer:${user} OR assignee:${user} "
+          + "OR cc:${user})";
 
   protected abstract Injector createInjector();
 
@@ -2585,7 +2588,10 @@
   protected class DashboardChangeState {
     private final Account.Id ownerId;
     private final List<Account.Id> reviewedBy;
+    private final List<Account.Id> cced;
     private final List<Account.Id> ignoredBy;
+    private final List<Account.Id> draftCommentBy;
+    private final List<Account.Id> deleteDraftCommentBy;
     private boolean wip;
     private boolean abandoned;
     @Nullable private Account.Id mergedBy;
@@ -2596,7 +2602,10 @@
     DashboardChangeState(Account.Id ownerId) {
       this.ownerId = ownerId;
       reviewedBy = new ArrayList<>();
+      cced = new ArrayList<>();
       ignoredBy = new ArrayList<>();
+      draftCommentBy = new ArrayList<>();
+      deleteDraftCommentBy = new ArrayList<>();
     }
 
     DashboardChangeState assignTo(Account.Id assigneeId) {
@@ -2629,6 +2638,21 @@
       return this;
     }
 
+    DashboardChangeState addCc(Account.Id ccId) {
+      cced.add(ccId);
+      return this;
+    }
+
+    DashboardChangeState draftCommentBy(Account.Id commenterId) {
+      draftCommentBy.add(commenterId);
+      return this;
+    }
+
+    DashboardChangeState draftAndDeleteCommentBy(Id commenterId) {
+      deleteDraftCommentBy.add(commenterId);
+      return this;
+    }
+
     DashboardChangeState create(TestRepository<Repo> repo) throws Exception {
       requestContext.setContext(newRequestContext(ownerId));
       Change change = insert(repo, newChange(repo), ownerId);
@@ -2648,11 +2672,28 @@
       for (Account.Id reviewerId : reviewedBy) {
         cApi.addReviewer("" + reviewerId);
       }
+      for (Account.Id reviewerId : cced) {
+        AddReviewerInput in = new AddReviewerInput();
+        in.reviewer = reviewerId.toString();
+        in.state = ReviewerState.CC;
+        cApi.addReviewer(in);
+      }
       for (Account.Id ignorerId : ignoredBy) {
         requestContext.setContext(newRequestContext(ignorerId));
         StarsInput in = new StarsInput(new HashSet<>(Arrays.asList("ignore")));
         gApi.accounts().self().setStars("" + id, in);
       }
+      DraftInput in = new DraftInput();
+      in.path = Patch.COMMIT_MSG;
+      in.message = "message";
+      for (Account.Id commenterId : draftCommentBy) {
+        requestContext.setContext(newRequestContext(commenterId));
+        gApi.changes().id(change.getChangeId()).current().createDraft(in);
+      }
+      for (Account.Id commenterId : deleteDraftCommentBy) {
+        requestContext.setContext(newRequestContext(commenterId));
+        gApi.changes().id(change.getChangeId()).current().createDraft(in).delete();
+      }
       if (mergedBy != null) {
         requestContext.setContext(newRequestContext(mergedBy));
         cApi = gApi.changes().id(change.getChangeId());
@@ -2674,6 +2715,23 @@
   }
 
   @Test
+  public void dashboardHasUnpublishedDrafts() throws Exception {
+    TestRepository<Repo> repo = createProject("repo");
+    Account.Id otherAccountId = createAccount("other");
+    DashboardChangeState hasUnpublishedDraft =
+        new DashboardChangeState(otherAccountId).draftCommentBy(user.getAccountId()).create(repo);
+
+    // Create changes that should not be returned by query.
+    new DashboardChangeState(user.getAccountId()).create(repo);
+    new DashboardChangeState(user.getAccountId()).draftCommentBy(otherAccountId).create(repo);
+    new DashboardChangeState(user.getAccountId())
+        .draftAndDeleteCommentBy(user.getAccountId())
+        .create(repo);
+
+    assertDashboardQuery("self", DASHBOARD_HAS_UNPUBLISHED_DRAFTS_QUERY, hasUnpublishedDraft);
+  }
+
+  @Test
   public void dashboardWorkInProgressReviews() throws Exception {
     TestRepository<Repo> repo = createProject("repo");
     DashboardChangeState ownedOpenWip =
@@ -2773,6 +2831,11 @@
             .ignoreBy(user.getAccountId())
             .mergeBy(user.getAccountId())
             .create(repo);
+    DashboardChangeState mergedCced =
+        new DashboardChangeState(otherAccountId)
+            .addCc(user.getAccountId())
+            .mergeBy(user.getAccountId())
+            .create(repo);
     DashboardChangeState mergedAssigned =
         new DashboardChangeState(otherAccountId)
             .assignTo(user.getAccountId())
@@ -2859,6 +2922,7 @@
         abandonedOwnedIgnoredByOther,
         abandonedOwned,
         mergedAssigned,
+        mergedCced,
         mergedReviewing,
         mergedOwnedIgnoredByOther,
         mergedOwned);
@@ -2877,6 +2941,7 @@
         abandonedOwned,
         mergedAssignedIgnoredByUser,
         mergedAssigned,
+        mergedCced,
         mergedReviewingIgnoredByUser,
         mergedReviewing,
         mergedOwned);
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
index d84dec5..b5156d7 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
@@ -22,7 +22,7 @@
 
   // NOTE: These queries are tested in Java. Any changes made to definitions
   // here require corresponding changes to:
-  // gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+  // javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
   const DEFAULT_SECTIONS = [
     {
       // Changes with unpublished draft comments. This section is omitted when