Fix _readResponsePayload runtime errors

Before I6398b74779, the REST API interface's `getResponseObject` did not
make use of any other methods, and thus did not need to be invoked with
a `this` context. When this changed, the handful of locations that
invoke `getResponseObject` without binding were broken silently,
resulting in runtime exceptions where the app fails to parse responses
to some network actions. For example, when deleting a topic.

With this change, the invocations use corrected bindings and tests are
added to confirm that runtime exceptions do not occur.

Change-Id: I682d3d5f5fc4aaec03762e17d32afec084bbdebf
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
index ab90585..406ec0c 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
@@ -1645,7 +1645,7 @@
     setChangeTopic(changeNum, topic) {
       const p = {topic};
       return this.getChangeURLAndSend(changeNum, 'PUT', null, '/topic', p)
-          .then(this.getResponseObject);
+          .then(this.getResponseObject.bind(this));
     },
 
     /**
@@ -1655,7 +1655,7 @@
      */
     setChangeHashtag(changeNum, hashtag) {
       return this.getChangeURLAndSend(changeNum, 'POST', null, '/hashtags',
-          hashtag).then(this.getResponseObject);
+          hashtag).then(this.getResponseObject.bind(this));
     },
 
     deleteAccountHttpPassword() {
@@ -1669,7 +1669,7 @@
      */
     generateAccountHttpPassword() {
       return this.send('PUT', '/accounts/self/password.http', {generate: true})
-          .then(this.getResponseObject);
+          .then(this.getResponseObject.bind(this));
     },
 
     getAccountSSHKeys() {
@@ -1772,7 +1772,7 @@
       const endpoint = `/comments/${commentID}/delete`;
       const payload = {reason};
       return this.getChangeURLAndSend(changeNum, 'POST', patchNum, endpoint,
-          payload).then(this.getResponseObject);
+          payload).then(this.getResponseObject.bind(this));
     },
 
     /**
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
index 2058f59..afa1c53 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
@@ -959,5 +959,29 @@
         assert.deepEqual(result, obj);
       });
     });
+
+    test('setChangeTopic', () => {
+      const sendSpy = sandbox.spy(element, 'getChangeURLAndSend');
+      return element.setChangeTopic(123, 'foo-bar').then(() => {
+        assert.isTrue(sendSpy.calledOnce);
+        assert.deepEqual(sendSpy.lastCall.args[4], {topic: 'foo-bar'});
+      });
+    });
+
+    test('setChangeHashtag', () => {
+      const sendSpy = sandbox.spy(element, 'getChangeURLAndSend');
+      return element.setChangeHashtag(123, 'foo-bar').then(() => {
+        assert.isTrue(sendSpy.calledOnce);
+        assert.equal(sendSpy.lastCall.args[4], 'foo-bar');
+      });
+    });
+
+    test('generateAccountHttpPassword', () => {
+      const sendSpy = sandbox.spy(element, 'send');
+      return element.generateAccountHttpPassword().then(() => {
+        assert.isTrue(sendSpy.calledOnce);
+        assert.deepEqual(sendSpy.lastCall.args[2], {generate: true});
+      });
+    });
   });
 </script>