Save top-level draft change comments in localstorage

Unsaved diff comment drafts are automatically backed-up in local-storage
if the user discards them on accident or navigates away without saving
them. This change extends the same functionality to change-level
comments and adds tests accordingly.

Bug: Issue 4258
Change-Id: Iecfdecfc10cd92f798f1f7306af994b6ec8f74db
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
index 0456be1..e65cc04 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
@@ -34,14 +34,27 @@
 <script>
   suite('gr-reply-dialog tests', function() {
     var element;
+    var changeNum;
+    var patchNum;
+
+    var sandbox;
+    var getDraftCommentStub;
+    var setDraftCommentStub;
+    var eraseDraftCommentStub;
 
     setup(function() {
+      sandbox = sinon.sandbox.create();
+
+      changeNum = 42;
+      patchNum = 1;
+
       stub('gr-rest-api-interface', {
         getAccount: function() { return Promise.resolve({}); },
       });
+
       element = fixture('basic');
-      element.changeNum = 42;
-      element.patchNum = 1;
+      element.change = { _number: changeNum };
+      element.patchNum = patchNum;
       element.labels = {
         Verified: {
           values: {
@@ -75,10 +88,19 @@
         ]
       };
 
+      getDraftCommentStub = sandbox.stub(element.$.storage, 'getDraftComment');
+      setDraftCommentStub = sandbox.stub(element.$.storage, 'setDraftComment');
+      eraseDraftCommentStub = sandbox.stub(element.$.storage,
+          'eraseDraftComment');
+
       // Allow the elements created by dom-repeat to be stamped.
       flushAsynchronousOperations();
     });
 
+    teardown(function() {
+      sandbox.restore();
+    });
+
     test('cancel event', function(done) {
       element.addEventListener('cancel', function() { done(); });
       MockInteractions.tap(element.$$('.cancel'));
@@ -231,5 +253,42 @@
         assert.equal(getActiveElement().id, 'input');
       }).then(done);
     });
+
+    test('_getStorageLocation', function() {
+      var actual = element._getStorageLocation();
+      assert.equal(actual.changeNum, changeNum);
+      assert.equal(actual.patchNum, patchNum);
+      assert.equal(actual.path, '@change');
+    });
+
+    test('gets draft from storage on open', function() {
+      var storedDraft = 'hello world';
+      getDraftCommentStub.returns({message: storedDraft});
+      element.open();
+      assert.isTrue(getDraftCommentStub.called);
+      assert.equal(element.draft, storedDraft);
+    });
+
+    test('blank if no stored draft', function() {
+      getDraftCommentStub.returns(null);
+      element.open();
+      assert.isTrue(getDraftCommentStub.called);
+      assert.equal(element.draft, '');
+    });
+
+    test('updates stored draft on edits', function() {
+      var firstEdit = 'hello';
+      var location = element._getStorageLocation();
+
+      element.draft = firstEdit;
+      element.flushDebouncer('store');
+
+      assert.isTrue(setDraftCommentStub.calledWith(location, firstEdit));
+
+      element.draft = '';
+      element.flushDebouncer('store');
+
+      assert.isTrue(eraseDraftCommentStub.calledWith(location));
+    });
   });
 </script>