Add experimental labelchange event in JS API

It’s useful to know when a label is changed so that action can
be taken within the change view. For instance, actions added to
the interface by the plugin may need to be updated.

Feature: Issue 3915
Change-Id: I9f95d6fcb9a15970ef3ed74fad15588074d6847a
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 cf4edf3..3a7fe0b 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
@@ -16,6 +16,7 @@
 
   var EventType = {
     HISTORY: 'history',
+    LABEL_CHANGE: 'labelchange',
     SHOW_CHANGE: 'showchange',
     SUBMIT_CHANGE: 'submitchange',
     COMMENT: 'comment',
@@ -53,6 +54,9 @@
         case EventType.COMMENT:
           this._handleComment(detail);
           break;
+        case EventType.LABEL_CHANGE:
+          this._handleLabelChange(detail);
+          break;
         default:
           console.warn('handleEvent called with unsupported event type:', type);
           break;
@@ -133,6 +137,16 @@
       });
     },
 
+    _handleLabelChange: function(detail) {
+      this._getEventCallbacks(EventType.LABEL_CHANGE).forEach(function(cb) {
+        try {
+          cb(detail.change);
+        } catch (err) {
+          console.error(err);
+        }
+      });
+    },
+
     _getEventCallbacks: function(type) {
       return this._eventCallbacks[type] || [];
     },
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html
index 76fa91b..959ba64 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html
@@ -97,6 +97,17 @@
       element.handleEvent(element.EventType.COMMENT, {node: testCommentNode});
     });
 
+    test('labelchange event', function(done) {
+      var testChange = {_number: 42};
+      plugin.on(element.EventType.LABEL_CHANGE, throwErrFn);
+      plugin.on(element.EventType.LABEL_CHANGE, function(change) {
+        assert.deepEqual(change, testChange);
+        assert.isTrue(errorStub.calledOnce);
+        done();
+      });
+      element.handleEvent(element.EventType.LABEL_CHANGE, {change: testChange});
+    });
+
     test('submitchange', function() {
       plugin.on(element.EventType.SUBMIT_CHANGE, throwErrFn);
       plugin.on(element.EventType.SUBMIT_CHANGE, function() { return true; });