Merge "Support notify settings for posting checks"
diff --git a/README.md b/README.md
index f8b7169..4a61e1e 100644
--- a/README.md
+++ b/README.md
@@ -5,5 +5,6 @@
 
 This plugin uses [polymer-cli](https://www.polymer-project.org/1.0/docs/tools/polymer-cli#install) to test.
 
-After `bower install`, running `polymer test -l chrome` will run all tests in Chrome, and running `polymer serve` and navigating to http://127.0.0.1:8081/components/checks/gr-checks/gr-checks-view_test.html allows for manual debugging.
+After `bower install`, running `polymer test -l chrome` will run all tests in Chrome, and running `polymer serve`
+and navigating to http://127.0.0.1:8081/components/checks/gr-checks/gr-checks-view_test.html allows for manual debugging.
 
diff --git a/gr-checks/gr-checkers-list.html b/gr-checks/gr-checkers-list.html
index 6c62e4d..5eb5a76 100644
--- a/gr-checks/gr-checkers-list.html
+++ b/gr-checks/gr-checkers-list.html
@@ -57,107 +57,108 @@
       }
     </style>
 
-
-    <div id="topContainer">
-      <div>
-        <label>Filter:</label>
-        <iron-input
-            type="text"
-            bind-value="{{_filter}}">
-          <input
-              is="iron-input"
+    <gr-overlay on-fullscreen-overlay-closed="_handleOverlayClosed" id="listOverlay" with-backdrop>
+      <div id="topContainer">
+        <div>
+          <label>Filter:</label>
+          <iron-input
               type="text"
-              id="filter"
               bind-value="{{_filter}}">
-        </iron-input>
+            <input
+                is="iron-input"
+                type="text"
+                id="filter"
+                bind-value="{{_filter}}">
+          </iron-input>
+        </div>
+        <div id="createNewContainer"
+            class$="[[_computeCreateClass(_createNewCapability)]]">
+          <gr-button primary link id="createNew" on-tap="_handleCreateClicked">
+            Create New
+          </gr-button>
+        </div>
       </div>
-      <div id="createNewContainer"
-          class$="[[_computeCreateClass(_createNewCapability)]]">
-        <gr-button primary link id="createNew" on-tap="_handleCreateClicked">
-          Create New
-        </gr-button>
-      </div>
-    </div>
 
-    <table id="list" class="genericList">
-      <tr class="headerRow">
-        <th class="name topHeader">Checker Name</th>
-        <th class="name topHeader">Repository</th>
-        <th class="name topHeader">Status</th>
-        <th class="name topHeader">Required</th>
-        <th class="topHeader description">Checker Description</th>
-        <th class="name topHeader"> Edit </th>
-      </tr>
-      <tbody class$="[[computeLoadingClass(_loading)]]">
-        <template is="dom-repeat" items="[[_visibleCheckers]]">
-          <tr class="table">
-            <td class="name">
-              <a>[[item.name]]</a>
-            </td>
-            <td class="name">[[item.repository]]</td>
-            <td class="name">[[item.status]]</td>
-            <td class="name">[[_computeBlocking(item)]]</td>
-            <td class="description">[[item.description]]</td>
-            <td on-tap="_handleEditIconClicked">
-              <iron-icon icon="gr-icons:edit"></iron-icon>
-            </td>
-          </tr>
+      <table id="list" class="genericList">
+        <tr class="headerRow">
+          <th class="name topHeader">Checker Name</th>
+          <th class="name topHeader">Repository</th>
+          <th class="name topHeader">Status</th>
+          <th class="name topHeader">Required</th>
+          <th class="topHeader description">Checker Description</th>
+          <th class="name topHeader"> Edit </th>
+        </tr>
+        <tbody id="listBody" class$="[[computeLoadingClass(_loading)]]">
+          <template is="dom-repeat" items="[[_visibleCheckers]]">
+            <tr class="table">
+              <td class="name">
+                <a>[[item.name]]</a>
+              </td>
+              <td class="name">[[item.repository]]</td>
+              <td class="name">[[item.status]]</td>
+              <td class="name">[[_computeBlocking(item)]]</td>
+              <td class="description">[[item.description]]</td>
+              <td on-tap="_handleEditIconClicked">
+                <iron-icon icon="gr-icons:edit"></iron-icon>
+              </td>
+            </tr>
+          </template>
+        </tbody>
+      </table>
+
+      <nav>
+        <template is="dom-if" if="[[_showPrevButton]]">
+          <a class="nav-buttons" id="prevArrow"
+            on-tap="_handlePrevClicked">
+            <iron-icon class="nav-iron-icon" icon="gr-icons:chevron-left"></iron-icon>
+          </a>
         </template>
-      </tbody>
-    </table>
+        <template is="dom-if" if="[[_showNextButton]]">
+          <a class="nav-buttons" id="nextArrow"
+            on-tap="_handleNextClicked">
+            <iron-icon icon="gr-icons:chevron-right"></iron-icon>
+          </a>
+        </template>
+      </nav>
 
-    <nav>
-      <template is="dom-if" if="[[_showPrevButton]]">
-        <a class="nav-buttons" id="prevArrow"
-          on-tap="_handlePrevClicked">
-          <iron-icon class="nav-iron-icon" icon="gr-icons:chevron-left"></iron-icon>
-        </a>
-      </template>
-      <template is="dom-if" if="[[_showNextButton]]">
-        <a class="nav-buttons" id="nextArrow"
-          on-tap="_handleNextClicked">
-          <iron-icon icon="gr-icons:chevron-right"></iron-icon>
-        </a>
-      </template>
-    </nav>
-
-    <gr-overlay id="createOverlay">
-      <gr-dialog
-          id="createDialog"
-          confirm-label="Create"
-          on-confirm="_handleCreateConfirm"
-          on-cancel="_handleCreateCancel">
-        <div class="header" slot="header">
-          Create Checkers
-        </div>
-        <div slot="main">
-          <gr-create-checkers-dialog
-            id="createNewModal"
-            plugin-rest-api="[[pluginRestApi]]">
-          </gr-create-checkers-dialog>
-        </div>
-      </gr-dialog>
+      <gr-overlay id="createOverlay">
+        <gr-dialog
+            id="createDialog"
+            confirm-label="Create"
+            on-confirm="_handleCreateConfirm"
+            on-cancel="_handleCreateCancel">
+          <div class="header" slot="header">
+            Create Checkers
+          </div>
+          <div slot="main">
+            <gr-create-checkers-dialog
+              id="createNewModal"
+              plugin-rest-api="[[pluginRestApi]]">
+            </gr-create-checkers-dialog>
+          </div>
+        </gr-dialog>
+      </gr-overlay>
+      <gr-overlay id="editOverlay">
+        <gr-dialog
+            id="editDialog"
+            confirm-label="Save"
+            on-confirm="_handleEditConfirm"
+            on-cancel="_handleEditCancel">
+          <div class="header" slot="header">
+            Edit Checker
+          </div>
+          <div slot="main">
+            <gr-create-checkers-dialog
+                checker="[[checker]]"
+                plugin-rest-api="[[pluginRestApi]]"
+                on-cancel="_handleEditCancel"
+                id="editModal">
+            </gr-create-checkers-dialog>
+          </div>
+        </gr-dialog>
+      </gr-overlay>
     </gr-overlay>
-    <gr-overlay id="editOverlay">
-      <gr-dialog
-          id="editDialog"
-          confirm-label="Save"
-          on-confirm="_handleEditConfirm"
-          on-cancel="_handleEditCancel">
-        <div class="header" slot="header">
-          Edit Checker
-        </div>
-        <div slot="main">
-          <gr-create-checkers-dialog
-              checker="[[checker]]"
-              plugin-rest-api="[[pluginRestApi]]"
-              on-cancel="_handleEditCancel"
-              id="editModal">
-          </gr-create-checkers-dialog>
-        </div>
-      </gr-dialog>
-    </gr-overlay>
-      <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
+    <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
   </template>
   <script src="gr-checkers-list.js"></script>
 </dom-module>
diff --git a/gr-checks/gr-checkers-list.js b/gr-checks/gr-checkers-list.js
index 4914274..b07b861 100644
--- a/gr-checks/gr-checkers-list.js
+++ b/gr-checks/gr-checkers-list.js
@@ -16,7 +16,6 @@
        */
       pluginRestApi: {
         type: Object,
-        observer: '_getCheckers'
       },
       // Checker that will be passed to the editOverlay modal
       checker: Object,
@@ -34,7 +33,6 @@
       _visibleCheckers: {
         type: Array,
         computed: '_computeVisibleCheckers(_startingIndex, _filteredCheckers)',
-        observer: '_visibleCheckersChanged'
       },
       _createNewCapability: {
         type: Boolean,
@@ -59,17 +57,40 @@
       '_showCheckers(_checkers, _filter)',
     ],
 
+    attached() {
+      /**
+       * Adding an observer to listBody element as gr-overlay does not
+       * automatically resize itself once the getCheckers response comes.
+       * Polymer 2 will deprecate use of obserNodes so replacing it
+       * with FlattenedNodesObserver
+       */
+      if (Polymer.FlattenedNodesObserver) {
+        this._checkersListObserver = new Polymer.FlattenedNodesObserver(
+          this.$.listBody, () => {
+            this.$.listOverlay.refit();
+          });
+      } else {
+        this._checkersListObserver = Polymer.dom(this.$.listBody).observeNodes(
+          () => {
+            this.$.listOverlay.refit();
+          });
+      }
+    },
+
+    detached() {
+      Polymer.dom(this.$.listBody).unobserveNodes(this._checkersListObserver);
+    },
+
     _contains(target, keyword) {
       return target.toLowerCase().includes(keyword.toLowerCase().trim());
     },
 
-    _visibleCheckersChanged(currentVisibleCheckers, previousVisibleCheckers) {
-      if (!currentVisibleCheckers || !previousVisibleCheckers) {
-        return;
-      }
-      if (currentVisibleCheckers.length !== previousVisibleCheckers.length) {
-        this.fire('resize', {bubbles: false});
-      }
+    _showConfigureOverlay() {
+      this.$.listOverlay.open().then(
+        () => {
+          this._getCheckers();
+        }
+      )
     },
 
     _showCheckers(_checkers, _filter) {
@@ -121,9 +142,9 @@
       }
     },
 
-    _getCheckers(pluginRestApi) {
-      if (!pluginRestApi) return;
-      pluginRestApi.get(GET_CHECKERS_URL).then(checkers => {
+    _getCheckers() {
+      if (!this.pluginRestApi) return;
+      this.pluginRestApi.get(GET_CHECKERS_URL).then(checkers => {
         if (!checkers) { return; }
         this._checkers = checkers;
         this._startingIndex = 0;
diff --git a/gr-checks/gr-checks-chip-view.js b/gr-checks/gr-checks-chip-view.js
index a2933ef..ce7d6d5 100644
--- a/gr-checks/gr-checks-chip-view.js
+++ b/gr-checks/gr-checks-chip-view.js
@@ -128,6 +128,8 @@
      * @param {function(number, number): !Promise<!Object>} getChecks
      */
     _fetchChecks(change, revision, getChecks) {
+      if (!getChecks || !change || !revision) return;
+
       getChecks(change._number, revision._number).then(checks => {
         this.set('_hasChecks', checks.length > 0);
         if (checks.length > 0) {
diff --git a/gr-checks/gr-checks-view.html b/gr-checks/gr-checks-view.html
index 40b6390..f0f7c94 100644
--- a/gr-checks/gr-checks-view.html
+++ b/gr-checks/gr-checks-view.html
@@ -166,9 +166,7 @@
       </table>
     </template>
 
-    <gr-overlay id="listOverlay" with-backdrop>
-      <gr-checkers-list on-resize="_handleCheckersListResize" plugin-rest-api="[[pluginRestApi]]"></gr-checkers-list>
-    </gr-overlay>
+    <gr-checkers-list on-resize="_handleCheckersListResize" plugin-rest-api="[[pluginRestApi]]"></gr-checkers-list>
 
   </template>
   <script src="gr-checks-view.js"></script>
diff --git a/gr-checks/gr-checks-view.js b/gr-checks/gr-checks-view.js
index 3aa88b8..c0d32a1 100644
--- a/gr-checks/gr-checks-view.js
+++ b/gr-checks/gr-checks-view.js
@@ -98,7 +98,7 @@
     },
 
     _handleConfigureClicked() {
-      this.$.listOverlay.open();
+      this.$$('gr-checkers-list')._showConfigureOverlay();
     },
 
     _orderChecks(a, b) {
@@ -140,6 +140,8 @@
      * @param {function(number, number): !Promise<!Object>} getChecks
      */
     _fetchChecks(change, revision, getChecks) {
+      if (!getChecks || !change || !revision) return;
+
       getChecks(change._number, revision._number).then(checks => {
         if (checks && checks.length) {
           checks.sort(this._orderChecks);
diff --git a/java/com/google/gerrit/plugins/checks/testing/BUILD b/java/com/google/gerrit/plugins/checks/testing/BUILD
index 0f67a93..cd9d58e 100644
--- a/java/com/google/gerrit/plugins/checks/testing/BUILD
+++ b/java/com/google/gerrit/plugins/checks/testing/BUILD
@@ -15,7 +15,6 @@
         "//lib/jgit/org.eclipse.jgit:jgit",
         "//lib/truth",
         "//lib/truth:truth-java8-extension",
-        "//plugins:plugin-api",
         "//plugins/checks:checks__plugin",
     ],
 )
diff --git a/javatests/com/google/gerrit/plugins/checks/BUILD b/javatests/com/google/gerrit/plugins/checks/BUILD
index 814e5b8..20e807c 100644
--- a/javatests/com/google/gerrit/plugins/checks/BUILD
+++ b/javatests/com/google/gerrit/plugins/checks/BUILD
@@ -5,6 +5,7 @@
 junit_tests(
     name = "checks_tests",
     srcs = glob(["*.java"]),
+    runtime_deps = ["//java/com/google/gerrit/lucene"],
     deps = [
         "//java/com/google/gerrit/common:annotations",
         "//java/com/google/gerrit/extensions:api",
diff --git a/javatests/com/google/gerrit/plugins/checks/api/BUILD b/javatests/com/google/gerrit/plugins/checks/api/BUILD
index 9ef3a14..eeaabcd 100644
--- a/javatests/com/google/gerrit/plugins/checks/api/BUILD
+++ b/javatests/com/google/gerrit/plugins/checks/api/BUILD
@@ -5,7 +5,6 @@
     size = "small",
     srcs = glob(["*.java"]),
     deps = [
-        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//lib:guava",
         "//lib/truth",
         "//plugins/checks:checks__plugin",
diff --git a/javatests/com/google/gerrit/plugins/checks/db/BUILD b/javatests/com/google/gerrit/plugins/checks/db/BUILD
index 201f44d..4dc58a6 100644
--- a/javatests/com/google/gerrit/plugins/checks/db/BUILD
+++ b/javatests/com/google/gerrit/plugins/checks/db/BUILD
@@ -5,18 +5,10 @@
     size = "small",
     srcs = glob(["*.java"]),
     deps = [
-        "//java/com/google/gerrit/common:annotations",
-        "//java/com/google/gerrit/common:server",
-        "//java/com/google/gerrit/common/data/testing:common-data-test-util",
-        "//java/com/google/gerrit/extensions:api",
-        "//java/com/google/gerrit/extensions/common/testing:common-test-util",
-        "//java/com/google/gerrit/git",
-        "//java/com/google/gerrit/git/testing",
         "//java/com/google/gerrit/reviewdb:server",
         "//java/com/google/gerrit/server",
         "//java/com/google/gerrit/server/util/time",
         "//java/com/google/gerrit/testing:gerrit-test-util",
-        "//java/com/google/gerrit/truth",
         "//lib:guava",
         "//lib/jgit/org.eclipse.jgit:jgit",
         "//lib/jgit/org.eclipse.jgit.junit:junit",
diff --git a/javatests/com/google/gerrit/plugins/checks/rules/BUILD b/javatests/com/google/gerrit/plugins/checks/rules/BUILD
index 2e76709..f983cd4 100644
--- a/javatests/com/google/gerrit/plugins/checks/rules/BUILD
+++ b/javatests/com/google/gerrit/plugins/checks/rules/BUILD
@@ -6,13 +6,12 @@
     srcs = glob(["*.java"]),
     deps = [
         "//java/com/google/gerrit/common:server",
-        "//java/com/google/gerrit/exceptions",
         "//java/com/google/gerrit/reviewdb:server",
         "//java/com/google/gerrit/server",
         "//java/com/google/gerrit/server/util/time",
-        "//java/com/google/gerrit/testing:gerrit-test-util",
         "//lib:guava",
         "//lib/jgit/org.eclipse.jgit:jgit",
+        "//lib/mockito",
         "//lib/truth",
         "//lib/truth:truth-java8-extension",
         "//plugins/checks:checks__plugin",
diff --git a/javatests/com/google/gerrit/plugins/checks/rules/ChecksSubmitRuleTest.java b/javatests/com/google/gerrit/plugins/checks/rules/ChecksSubmitRuleTest.java
index 2d75e6b..ebfac2e 100644
--- a/javatests/com/google/gerrit/plugins/checks/rules/ChecksSubmitRuleTest.java
+++ b/javatests/com/google/gerrit/plugins/checks/rules/ChecksSubmitRuleTest.java
@@ -16,9 +16,9 @@
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth8.assertThat;
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import com.google.gerrit.common.data.SubmitRecord;
 import com.google.gerrit.plugins.checks.Checks;
@@ -30,21 +30,18 @@
 import com.google.gerrit.server.util.time.TimeUtil;
 import java.io.IOException;
 import java.util.Optional;
-import org.easymock.EasyMock;
 import org.eclipse.jgit.lib.ObjectId;
 import org.junit.Test;
 
 public class ChecksSubmitRuleTest {
   @Test
   public void loadingCurrentPatchSetFails() throws Exception {
-    ChecksSubmitRule checksSubmitRule =
-        new ChecksSubmitRule(EasyMock.createStrictMock(Checks.class));
+    ChecksSubmitRule checksSubmitRule = new ChecksSubmitRule(mock(Checks.class));
 
-    ChangeData cd = EasyMock.createStrictMock(ChangeData.class);
-    expect(cd.project()).andReturn(Project.nameKey("My-Project"));
-    expect(cd.getId()).andReturn(Change.id(1));
-    expect(cd.currentPatchSet()).andThrow(new IllegalStateException("Fail for test"));
-    replay(cd);
+    ChangeData cd = mock(ChangeData.class);
+    when(cd.project()).thenReturn(Project.nameKey("My-Project"));
+    when(cd.getId()).thenReturn(Change.id(1));
+    when(cd.currentPatchSet()).thenThrow(new IllegalStateException("Fail for test"));
 
     Optional<SubmitRecord> submitRecords = checksSubmitRule.evaluate(cd);
     assertErrorRecord(submitRecords, "failed to load the current patch set of change 1");
@@ -52,26 +49,24 @@
 
   @Test
   public void getCombinedCheckStateFails() throws Exception {
-    Checks checks = EasyMock.createStrictMock(Checks.class);
-    expect(checks.areAllRequiredCheckersPassing(anyObject(), anyObject()))
-        .andThrow(new IOException("Fail for test"));
-    replay(checks);
+    Checks checks = mock(Checks.class);
+    when(checks.areAllRequiredCheckersPassing(any(), any()))
+        .thenThrow(new IOException("Fail for test"));
 
     ChecksSubmitRule checksSubmitRule = new ChecksSubmitRule(checks);
 
     Change.Id changeId = Change.id(1);
-    ChangeData cd = EasyMock.createStrictMock(ChangeData.class);
-    expect(cd.project()).andReturn(Project.nameKey("My-Project"));
-    expect(cd.getId()).andReturn(Change.id(1));
-    expect(cd.currentPatchSet())
-        .andReturn(
+    ChangeData cd = mock(ChangeData.class);
+    when(cd.project()).thenReturn(Project.nameKey("My-Project"));
+    when(cd.getId()).thenReturn(Change.id(1));
+    when(cd.currentPatchSet())
+        .thenReturn(
             PatchSet.builder()
                 .id(PatchSet.id(changeId, 1))
                 .commitId(ObjectId.zeroId())
                 .uploader(Account.id(1000))
                 .createdOn(TimeUtil.nowTs())
                 .build());
-    replay(cd);
 
     Optional<SubmitRecord> submitRecords = checksSubmitRule.evaluate(cd);
     assertErrorRecord(submitRecords, "failed to evaluate check states for change 1");