Add change view reply dialog JS interface

Very similar to I2f82060ea14adef93a7018b79bf7cf10b84e5735

Only allows setting arbitrary label values and triggering a send
at this time.

Feature: Issue 3915
Change-Id: I6fda4cce7be767e104bba7b141b19b726c1a8954
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html
index a364c79..556691a 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html
@@ -19,6 +19,7 @@
 <link rel="import" href="../../../bower_components/iron-selector/iron-selector.html">
 <link rel="import" href="../../../behaviors/rest-client-behavior.html">
 <link rel="import" href="../../shared/gr-button/gr-button.html">
+<link rel="import" href="../../shared/gr-js-api-interface/gr-js-api-interface.html">
 <link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
 
 <dom-module id="gr-reply-dialog">
@@ -154,6 +155,7 @@
             on-tap="_cancelTapHandler">Cancel</gr-button>
       </section>
     </div>
+    <gr-js-api-interface id="jsAPI"></gr-js-api-interface>
     <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
   </template>
   <script src="gr-reply-dialog.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js
index a702899..0ee779e 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js
@@ -59,6 +59,10 @@
       }.bind(this));
     },
 
+    ready: function() {
+      this.$.jsAPI.addElement(this.$.jsAPI.Element.REPLY_DIALOG, this);
+    },
+
     focus: function() {
       this.async(function() {
         this.$.textarea.textarea.focus();
@@ -72,6 +76,48 @@
       };
     },
 
+    setLabelValue: function(label, value) {
+      var selectorEl = this.$$('iron-selector[data-label="' + label + '"]');
+      // The selector may not be present if it’s not at the latest patch set.
+      if (!selectorEl) { return; }
+      var item = selectorEl.$$('gr-button[data-value="' + value + '"]');
+      if (!item) { return; }
+      selectorEl.selectIndex(selectorEl.indexOf(item));
+    },
+
+    send: function() {
+      var obj = {
+        drafts: 'PUBLISH_ALL_REVISIONS',
+        labels: {},
+      };
+      for (var label in this.permittedLabels) {
+        if (!this.permittedLabels.hasOwnProperty(label)) { continue; }
+
+        var selectorEl = this.$$('iron-selector[data-label="' + label + '"]');
+
+        // The selector may not be present if it’s not at the latest patch set.
+        if (!selectorEl) { continue; }
+
+        var selectedVal = selectorEl.selectedItem.getAttribute('data-value');
+        selectedVal = parseInt(selectedVal, 10);
+        obj.labels[label] = selectedVal;
+      }
+      if (this.draft != null) {
+        obj.message = this.draft;
+      }
+      this.disabled = true;
+      return this._saveReview(obj).then(function(response) {
+        this.disabled = false;
+        if (!response.ok) { return response; }
+
+        this.draft = '';
+        this.fire('send', null, {bubbles: false});
+      }.bind(this)).catch(function(err) {
+        this.disabled = false;
+        throw err;
+      }.bind(this));
+    },
+
     _computeShowLabels: function(patchNum, revisions) {
       var num = parseInt(patchNum, 10);
       for (var rev in revisions) {
@@ -147,34 +193,7 @@
 
     _sendTapHandler: function(e) {
       e.preventDefault();
-      var obj = {
-        drafts: 'PUBLISH_ALL_REVISIONS',
-        labels: {},
-      };
-      for (var label in this.permittedLabels) {
-        var selectorEl = this.$$('iron-selector[data-label="' + label + '"]');
-
-        // The selector may not be present if it’s not at the latest patch set.
-        if (!selectorEl) { continue; }
-
-        var selectedVal = selectorEl.selectedItem.getAttribute('data-value');
-        selectedVal = parseInt(selectedVal, 10);
-        obj.labels[label] = selectedVal;
-      }
-      if (this.draft != null) {
-        obj.message = this.draft;
-      }
-      this.disabled = true;
-      this._saveReview(obj).then(function(response) {
-        this.disabled = false;
-        if (!response.ok) { return response; }
-
-        this.draft = '';
-        this.fire('send', null, {bubbles: false});
-      }.bind(this)).catch(function(err) {
-        this.disabled = false;
-        throw err;
-      }.bind(this));
+      this.send();
     },
 
     _saveReview: function(review) {
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api.js
new file mode 100644
index 0000000..9d6b83b
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api.js
@@ -0,0 +1,30 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+(function(window) {
+  'use strict';
+
+  function GrChangeReplyInterface(el) {
+    this._el = el;
+  }
+
+  GrChangeReplyInterface.prototype.setLabelValue = function(label, value) {
+    this._el.setLabelValue(label, value);
+  };
+
+  GrChangeReplyInterface.prototype.send = function() {
+    return this._el.send();
+  };
+
+  window.GrChangeReplyInterface = GrChangeReplyInterface;
+})(window);
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api_test.html
new file mode 100644
index 0000000..2e5aa56
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api_test.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
+<title>gr-change-reply-js-api</title>
+
+<script src="../../../bower_components/webcomponentsjs/webcomponents.min.js"></script>
+<script src="../../../bower_components/web-component-tester/browser.js"></script>
+
+<link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
+<!--
+This must refer to the element this interface is wrapping around. Otherwise
+breaking changes to gr-reply-dialog won’t be noticed.
+-->
+<link rel="import" href="../../change/gr-reply-dialog/gr-reply-dialog.html">
+
+<test-fixture id="basic">
+  <template>
+    <gr-reply-dialog></gr-reply-dialog>
+  </template>
+</test-fixture>
+
+<script>
+  suite('gr-change-reply-js-api tests', function() {
+    var element;
+    var sandbox;
+    var changeReply;
+
+    setup(function() {
+      stub('gr-rest-api-interface', {
+        getAccount: function() { return Promise.resolve(null); },
+      });
+      element = fixture('basic');
+      sandbox = sinon.sandbox.create();
+      var plugin;
+      Gerrit.install(function(p) { plugin = p; }, '0.1',
+          'http://test.com/plugins/testplugin/static/test.js');
+      changeReply = plugin.changeReply();
+    });
+
+    teardown(function() {
+      changeReply = null;
+      sandbox.restore();
+    });
+
+    test('calls', function() {
+      var setLabelValueStub = sinon.stub(element, 'setLabelValue');
+      changeReply.setLabelValue('My-Label', '+1337');
+      assert(setLabelValueStub.calledWithExactly('My-Label', '+1337'));
+
+      var sendStub = sinon.stub(element, 'send');
+      changeReply.send();
+      assert(sendStub.calledWithExactly());
+    });
+  });
+</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.html
index a77a4ea..22ec900 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.html
@@ -18,6 +18,7 @@
 <dom-module id="gr-js-api-interface">
   <template></template>
   <script src="gr-change-actions-js-api.js"></script>
+  <script src="gr-change-reply-js-api.js"></script>
   <script src="gr-js-api-interface.js"></script>
   <script src="gr-public-js-api.js"></script>
 </dom-module>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.js
index 3a7fe0b..bb37085 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.js
@@ -24,6 +24,7 @@
 
   var Element = {
     CHANGE_ACTIONS: 'changeactions',
+    REPLY_DIALOG: 'replydialog',
   };
 
   Polymer({
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
index e60876c..60b4205 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
@@ -57,6 +57,11 @@
         Plugin._sharedAPIElement.Element.CHANGE_ACTIONS));
   };
 
+  Plugin.prototype.changeReply = function() {
+    return new GrChangeReplyInterface(Plugin._sharedAPIElement.getElement(
+        Plugin._sharedAPIElement.Element.REPLY_DIALOG));
+  };
+
   var Gerrit = window.Gerrit || {};
 
   Gerrit.getPluginName = function() {
diff --git a/polygerrit-ui/app/test/index.html b/polygerrit-ui/app/test/index.html
index 8757ddf..f80f7ba 100644
--- a/polygerrit-ui/app/test/index.html
+++ b/polygerrit-ui/app/test/index.html
@@ -75,6 +75,7 @@
     'shared/gr-editable-content/gr-editable-content_test.html',
     'shared/gr-editable-label/gr-editable-label_test.html',
     'shared/gr-js-api-interface/gr-change-actions-js-api_test.html',
+    'shared/gr-js-api-interface/gr-change-reply-js-api_test.html',
     'shared/gr-js-api-interface/gr-js-api-interface_test.html',
     'shared/gr-linked-text/gr-linked-text_test.html',
     'shared/gr-rest-api-interface/gr-rest-api-interface_test.html',