Replace some deprecate done()s in frontend tests
				
					
				
			Replace 20% of all done() usages in frontend tests. Replaces all usages in elements/shared/... showcasing that there is no instance where the usage of done() is justified. Change-Id: I24b5644cd96c68097429583c44ae58301df374d6
This commit is contained in:
		@@ -38,10 +38,8 @@ suite('gr-account-entry tests', () => {
 | 
			
		||||
    some_other_property: 'other value',
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  setup(done => {
 | 
			
		||||
  setup(() => {
 | 
			
		||||
    element = basicFixture.instantiate();
 | 
			
		||||
 | 
			
		||||
    return flush(done);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  suite('stubbed values for querySuggestions', () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -156,7 +156,7 @@ suite('gr-account-list tests', () => {
 | 
			
		||||
    assert.isFalse(chips[0].classList.contains('pendingAdd'));
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('_getSuggestions uses filter correctly', done => {
 | 
			
		||||
  test('_getSuggestions uses filter correctly', () => {
 | 
			
		||||
    const originalSuggestions = [
 | 
			
		||||
      {
 | 
			
		||||
        email: 'abc@example.com',
 | 
			
		||||
@@ -184,7 +184,7 @@ suite('gr-account-list tests', () => {
 | 
			
		||||
          };
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    element._getSuggestions().then(suggestions => {
 | 
			
		||||
    return element._getSuggestions().then(suggestions => {
 | 
			
		||||
      // Default is no filtering.
 | 
			
		||||
      assert.equal(suggestions.length, 3);
 | 
			
		||||
 | 
			
		||||
@@ -194,14 +194,13 @@ suite('gr-account-list tests', () => {
 | 
			
		||||
        return suggestion._account_id === accountId;
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      element._getSuggestions()
 | 
			
		||||
          .then(suggestions => {
 | 
			
		||||
            assert.deepEqual(suggestions,
 | 
			
		||||
                [{name: originalSuggestions[0].email,
 | 
			
		||||
                  value: originalSuggestions[0]._account_id}]);
 | 
			
		||||
          })
 | 
			
		||||
          .then(done);
 | 
			
		||||
    });
 | 
			
		||||
      return element._getSuggestions();
 | 
			
		||||
    })
 | 
			
		||||
        .then(suggestions => {
 | 
			
		||||
          assert.deepEqual(suggestions,
 | 
			
		||||
              [{name: originalSuggestions[0].email,
 | 
			
		||||
                value: originalSuggestions[0]._account_id}]);
 | 
			
		||||
        });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('_computeChipClass', () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -39,11 +39,13 @@ suite('gr-alert tests', () => {
 | 
			
		||||
    assert.isNull(element.parentNode);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('action event', done => {
 | 
			
		||||
  test('action event', () => {
 | 
			
		||||
    const spy = sinon.spy();
 | 
			
		||||
    element.show();
 | 
			
		||||
    element._actionCallback = done;
 | 
			
		||||
    MockInteractions.tap(element.shadowRoot
 | 
			
		||||
        .querySelector('.action'));
 | 
			
		||||
    element._actionCallback = spy;
 | 
			
		||||
    assert.isFalse(spy.called);
 | 
			
		||||
    MockInteractions.tap(element.shadowRoot.querySelector('.action'));
 | 
			
		||||
    assert.isTrue(spy.called);
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -42,12 +42,11 @@ suite('gr-autocomplete-dropdown', () => {
 | 
			
		||||
    assert.equal(els[1].innerText.trim(), '2');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('escape key', done => {
 | 
			
		||||
  test('escape key', () => {
 | 
			
		||||
    const closeSpy = sinon.spy(element, 'close');
 | 
			
		||||
    MockInteractions.pressAndReleaseKeyOn(element, 27);
 | 
			
		||||
    flush();
 | 
			
		||||
    assert.isTrue(closeSpy.called);
 | 
			
		||||
    done();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('tab key', () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -81,7 +81,7 @@ suite('gr-autocomplete tests', () => {
 | 
			
		||||
    assert.isTrue(selectionStub.called);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('esc key behavior', done => {
 | 
			
		||||
  test('esc key behavior', () => {
 | 
			
		||||
    let promise;
 | 
			
		||||
    const queryStub = sinon.spy(() => promise = Promise.resolve([
 | 
			
		||||
      {name: 'blah', value: 123},
 | 
			
		||||
@@ -93,7 +93,7 @@ suite('gr-autocomplete tests', () => {
 | 
			
		||||
    element._focused = true;
 | 
			
		||||
    element.text = 'blah';
 | 
			
		||||
 | 
			
		||||
    promise.then(() => {
 | 
			
		||||
    return promise.then(() => {
 | 
			
		||||
      assert.isFalse(element.$.suggestions.isHidden);
 | 
			
		||||
 | 
			
		||||
      const cancelHandler = sinon.spy();
 | 
			
		||||
@@ -106,11 +106,10 @@ suite('gr-autocomplete tests', () => {
 | 
			
		||||
 | 
			
		||||
      MockInteractions.pressAndReleaseKeyOn(element.$.input, 27, null, 'esc');
 | 
			
		||||
      assert.isTrue(cancelHandler.called);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('emits commit and handles cursor movement', done => {
 | 
			
		||||
  test('emits commit and handles cursor movement', () => {
 | 
			
		||||
    let promise;
 | 
			
		||||
    const queryStub = sinon.spy(input => promise = Promise.resolve([
 | 
			
		||||
      {name: input + ' 0', value: 0},
 | 
			
		||||
@@ -126,7 +125,7 @@ suite('gr-autocomplete tests', () => {
 | 
			
		||||
    element._focused = true;
 | 
			
		||||
    element.text = 'blah';
 | 
			
		||||
 | 
			
		||||
    promise.then(() => {
 | 
			
		||||
    return promise.then(() => {
 | 
			
		||||
      assert.isFalse(element.$.suggestions.isHidden);
 | 
			
		||||
 | 
			
		||||
      const commitHandler = sinon.spy();
 | 
			
		||||
@@ -156,11 +155,10 @@ suite('gr-autocomplete tests', () => {
 | 
			
		||||
      assert.equal(commitHandler.getCall(0).args[0].detail.value, 1);
 | 
			
		||||
      assert.isTrue(element.$.suggestions.isHidden);
 | 
			
		||||
      assert.isTrue(element._focused);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('clear-on-commit behavior (off)', done => {
 | 
			
		||||
  test('clear-on-commit behavior (off)', () => {
 | 
			
		||||
    let promise;
 | 
			
		||||
    const queryStub = sinon.spy(() => {
 | 
			
		||||
      promise = Promise.resolve([{name: 'suggestion', value: 0}]);
 | 
			
		||||
@@ -170,7 +168,7 @@ suite('gr-autocomplete tests', () => {
 | 
			
		||||
    focusOnInput(element);
 | 
			
		||||
    element.text = 'blah';
 | 
			
		||||
 | 
			
		||||
    promise.then(() => {
 | 
			
		||||
    return promise.then(() => {
 | 
			
		||||
      const commitHandler = sinon.spy();
 | 
			
		||||
      element.addEventListener('commit', commitHandler);
 | 
			
		||||
 | 
			
		||||
@@ -179,11 +177,10 @@ suite('gr-autocomplete tests', () => {
 | 
			
		||||
 | 
			
		||||
      assert.isTrue(commitHandler.called);
 | 
			
		||||
      assert.equal(element.text, 'suggestion');
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('clear-on-commit behavior (on)', done => {
 | 
			
		||||
  test('clear-on-commit behavior (on)', () => {
 | 
			
		||||
    let promise;
 | 
			
		||||
    const queryStub = sinon.spy(() => {
 | 
			
		||||
      promise = Promise.resolve([{name: 'suggestion', value: 0}]);
 | 
			
		||||
@@ -194,7 +191,7 @@ suite('gr-autocomplete tests', () => {
 | 
			
		||||
    element.text = 'blah';
 | 
			
		||||
    element.clearOnCommit = true;
 | 
			
		||||
 | 
			
		||||
    promise.then(() => {
 | 
			
		||||
    return promise.then(() => {
 | 
			
		||||
      const commitHandler = sinon.spy();
 | 
			
		||||
      element.addEventListener('commit', commitHandler);
 | 
			
		||||
 | 
			
		||||
@@ -203,7 +200,6 @@ suite('gr-autocomplete tests', () => {
 | 
			
		||||
 | 
			
		||||
      assert.isTrue(commitHandler.called);
 | 
			
		||||
      assert.equal(element.text, '');
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@@ -246,7 +242,7 @@ suite('gr-autocomplete tests', () => {
 | 
			
		||||
    assert.equal(element._suggestions.length, 0);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('when focused', done => {
 | 
			
		||||
  test('when focused', () => {
 | 
			
		||||
    let promise;
 | 
			
		||||
    const queryStub = sinon.stub()
 | 
			
		||||
        .returns(promise = Promise.resolve([
 | 
			
		||||
@@ -258,14 +254,13 @@ suite('gr-autocomplete tests', () => {
 | 
			
		||||
    element.text = 'bla';
 | 
			
		||||
    assert.equal(element._focused, true);
 | 
			
		||||
    flush();
 | 
			
		||||
    promise.then(() => {
 | 
			
		||||
    return promise.then(() => {
 | 
			
		||||
      assert.equal(element._suggestions.length, 1);
 | 
			
		||||
      assert.equal(queryStub.notCalled, false);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('when not focused', done => {
 | 
			
		||||
  test('when not focused', () => {
 | 
			
		||||
    let promise;
 | 
			
		||||
    const queryStub = sinon.stub()
 | 
			
		||||
        .returns(promise = Promise.resolve([
 | 
			
		||||
@@ -276,13 +271,12 @@ suite('gr-autocomplete tests', () => {
 | 
			
		||||
    element.text = 'bla';
 | 
			
		||||
    assert.equal(element._focused, false);
 | 
			
		||||
    flush();
 | 
			
		||||
    promise.then(() => {
 | 
			
		||||
    return promise.then(() => {
 | 
			
		||||
      assert.equal(element._suggestions.length, 0);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('suggestions should not carry over', done => {
 | 
			
		||||
  test('suggestions should not carry over', () => {
 | 
			
		||||
    let promise;
 | 
			
		||||
    const queryStub = sinon.stub()
 | 
			
		||||
        .returns(promise = Promise.resolve([
 | 
			
		||||
@@ -292,15 +286,14 @@ suite('gr-autocomplete tests', () => {
 | 
			
		||||
    focusOnInput(element);
 | 
			
		||||
    element.text = 'bla';
 | 
			
		||||
    flush();
 | 
			
		||||
    promise.then(() => {
 | 
			
		||||
    return promise.then(() => {
 | 
			
		||||
      assert.equal(element._suggestions.length, 1);
 | 
			
		||||
      element._updateSuggestions('', 0, false);
 | 
			
		||||
      assert.equal(element._suggestions.length, 0);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('multi completes only the last part of the query', done => {
 | 
			
		||||
  test('multi completes only the last part of the query', () => {
 | 
			
		||||
    let promise;
 | 
			
		||||
    const queryStub = sinon.stub()
 | 
			
		||||
        .returns(promise = Promise.resolve([
 | 
			
		||||
@@ -311,7 +304,7 @@ suite('gr-autocomplete tests', () => {
 | 
			
		||||
    element.text = 'blah blah';
 | 
			
		||||
    element.multi = true;
 | 
			
		||||
 | 
			
		||||
    promise.then(() => {
 | 
			
		||||
    return promise.then(() => {
 | 
			
		||||
      const commitHandler = sinon.spy();
 | 
			
		||||
      element.addEventListener('commit', commitHandler);
 | 
			
		||||
 | 
			
		||||
@@ -320,7 +313,6 @@ suite('gr-autocomplete tests', () => {
 | 
			
		||||
 | 
			
		||||
      assert.isTrue(commitHandler.called);
 | 
			
		||||
      assert.equal(element.text, 'blah 0');
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -59,7 +59,7 @@ suite('gr-button tests', () => {
 | 
			
		||||
    assert.isFalse(paperBtn.disabled);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('loading set from listener', done => {
 | 
			
		||||
  test('loading set from listener', () => {
 | 
			
		||||
    let resolve;
 | 
			
		||||
    element.addEventListener('click', e => {
 | 
			
		||||
      e.target.loading = true;
 | 
			
		||||
@@ -71,11 +71,9 @@ suite('gr-button tests', () => {
 | 
			
		||||
    assert.isTrue(paperBtn.disabled);
 | 
			
		||||
    assert.isTrue(element.hasAttribute('loading'));
 | 
			
		||||
    resolve();
 | 
			
		||||
    flush(() => {
 | 
			
		||||
      assert.isFalse(paperBtn.disabled);
 | 
			
		||||
      assert.isFalse(element.hasAttribute('loading'));
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    flush();
 | 
			
		||||
    assert.isFalse(paperBtn.disabled);
 | 
			
		||||
    assert.isFalse(element.hasAttribute('loading'));
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('tabindex should be -1 if disabled', () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -45,24 +45,28 @@ suite('gr-change-star tests', () => {
 | 
			
		||||
    assert.equal(icon.icon, 'gr-icons:star-border');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('starring', done => {
 | 
			
		||||
    element.addEventListener('toggle-star', () => {
 | 
			
		||||
      assert.equal(element.change.starred, true);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  test('starring', async () => {
 | 
			
		||||
    let resolve;
 | 
			
		||||
    const promise = new Promise(r => resolve = r);
 | 
			
		||||
    element.addEventListener('toggle-star', resolve);
 | 
			
		||||
    element.set('change.starred', false);
 | 
			
		||||
    MockInteractions.tap(element.shadowRoot
 | 
			
		||||
        .querySelector('button'));
 | 
			
		||||
 | 
			
		||||
    await promise;
 | 
			
		||||
    assert.equal(element.change.starred, true);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('unstarring', done => {
 | 
			
		||||
    element.addEventListener('toggle-star', () => {
 | 
			
		||||
      assert.equal(element.change.starred, false);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  test('unstarring', async () => {
 | 
			
		||||
    let resolve;
 | 
			
		||||
    const promise = new Promise(r => resolve = r);
 | 
			
		||||
    element.addEventListener('toggle-star', resolve);
 | 
			
		||||
    element.set('change.starred', true);
 | 
			
		||||
    MockInteractions.tap(element.shadowRoot
 | 
			
		||||
        .querySelector('button'));
 | 
			
		||||
 | 
			
		||||
    await promise;
 | 
			
		||||
    assert.equal(element.change.starred, false);
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -24,12 +24,11 @@ const basicFixture = fixtureFromElement('gr-copy-clipboard');
 | 
			
		||||
suite('gr-copy-clipboard tests', () => {
 | 
			
		||||
  let element;
 | 
			
		||||
 | 
			
		||||
  setup(done => {
 | 
			
		||||
  setup(async () => {
 | 
			
		||||
    element = basicFixture.instantiate();
 | 
			
		||||
    element.text = `git fetch http://gerrit@localhost:8080/a/test-project
 | 
			
		||||
        refs/changes/05/5/1 && git checkout FETCH_HEAD`;
 | 
			
		||||
    flush();
 | 
			
		||||
    flush(done);
 | 
			
		||||
    await flush();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('copy to clipboard', () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,7 @@ suite('gr-date-formatter tests', () => {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function testDates(nowStr, dateStr, expected, expectedWithDateAndTime,
 | 
			
		||||
      expectedTooltip, done) {
 | 
			
		||||
      expectedTooltip) {
 | 
			
		||||
    // Normalize and convert the date to mimic server response.
 | 
			
		||||
    dateStr = normalizedDate(dateStr)
 | 
			
		||||
        .toJSON()
 | 
			
		||||
@@ -49,16 +49,14 @@ suite('gr-date-formatter tests', () => {
 | 
			
		||||
        .slice(0, -1);
 | 
			
		||||
    sinon.useFakeTimers(normalizedDate(nowStr).getTime());
 | 
			
		||||
    element.dateStr = dateStr;
 | 
			
		||||
    flush(() => {
 | 
			
		||||
      const span = element.shadowRoot
 | 
			
		||||
          .querySelector('span');
 | 
			
		||||
      assert.equal(span.textContent.trim(), expected);
 | 
			
		||||
      assert.equal(element.title, expectedTooltip);
 | 
			
		||||
      element.showDateAndTime = true;
 | 
			
		||||
      flush();
 | 
			
		||||
      assert.equal(span.textContent.trim(), expectedWithDateAndTime);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    flush();
 | 
			
		||||
    const span = element.shadowRoot
 | 
			
		||||
        .querySelector('span');
 | 
			
		||||
    assert.equal(span.textContent.trim(), expected);
 | 
			
		||||
    assert.equal(element.title, expectedTooltip);
 | 
			
		||||
    element.showDateAndTime = true;
 | 
			
		||||
    flush();
 | 
			
		||||
    assert.equal(span.textContent.trim(), expectedWithDateAndTime);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function stubRestAPI(preferences) {
 | 
			
		||||
@@ -87,36 +85,36 @@ suite('gr-date-formatter tests', () => {
 | 
			
		||||
      assert.equal(element._computeDateStr('foo', 'h:mm A'), '');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Within 24 hours on same day', done => {
 | 
			
		||||
    test('Within 24 hours on same day', () => {
 | 
			
		||||
      testDates('2015-07-29 20:34:14.985000000',
 | 
			
		||||
          '2015-07-29 15:34:14.985000000',
 | 
			
		||||
          '15:34',
 | 
			
		||||
          '15:34',
 | 
			
		||||
          'Jul 29, 2015, 15:34:14', done);
 | 
			
		||||
          'Jul 29, 2015, 15:34:14');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Within 24 hours on different days', done => {
 | 
			
		||||
    test('Within 24 hours on different days', () => {
 | 
			
		||||
      testDates('2015-07-29 03:34:14.985000000',
 | 
			
		||||
          '2015-07-28 20:25:14.985000000',
 | 
			
		||||
          'Jul 28',
 | 
			
		||||
          'Jul 28 20:25',
 | 
			
		||||
          'Jul 28, 2015, 20:25:14', done);
 | 
			
		||||
          'Jul 28, 2015, 20:25:14');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('More than 24 hours but less than six months', done => {
 | 
			
		||||
    test('More than 24 hours but less than six months', () => {
 | 
			
		||||
      testDates('2015-07-29 20:34:14.985000000',
 | 
			
		||||
          '2015-06-15 03:25:14.985000000',
 | 
			
		||||
          'Jun 15',
 | 
			
		||||
          'Jun 15 03:25',
 | 
			
		||||
          'Jun 15, 2015, 03:25:14', done);
 | 
			
		||||
          'Jun 15, 2015, 03:25:14');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('More than six months', done => {
 | 
			
		||||
    test('More than six months', () => {
 | 
			
		||||
      testDates('2015-09-15 20:34:00.000000000',
 | 
			
		||||
          '2015-01-15 03:25:00.000000000',
 | 
			
		||||
          'Jan 15, 2015',
 | 
			
		||||
          'Jan 15, 2015 03:25',
 | 
			
		||||
          'Jan 15, 2015, 03:25:00', done);
 | 
			
		||||
          'Jan 15, 2015, 03:25:00');
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@@ -131,28 +129,28 @@ suite('gr-date-formatter tests', () => {
 | 
			
		||||
      return element._loadPreferences();
 | 
			
		||||
    }));
 | 
			
		||||
 | 
			
		||||
    test('Within 24 hours on same day', done => {
 | 
			
		||||
    test('Within 24 hours on same day', () => {
 | 
			
		||||
      testDates('2015-07-29 20:34:14.985000000',
 | 
			
		||||
          '2015-07-29 15:34:14.985000000',
 | 
			
		||||
          '15:34',
 | 
			
		||||
          '15:34',
 | 
			
		||||
          '07/29/15, 15:34:14', done);
 | 
			
		||||
          '07/29/15, 15:34:14');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Within 24 hours on different days', done => {
 | 
			
		||||
    test('Within 24 hours on different days', () => {
 | 
			
		||||
      testDates('2015-07-29 03:34:14.985000000',
 | 
			
		||||
          '2015-07-28 20:25:14.985000000',
 | 
			
		||||
          '07/28',
 | 
			
		||||
          '07/28 20:25',
 | 
			
		||||
          '07/28/15, 20:25:14', done);
 | 
			
		||||
          '07/28/15, 20:25:14');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('More than 24 hours but less than six months', done => {
 | 
			
		||||
    test('More than 24 hours but less than six months', () => {
 | 
			
		||||
      testDates('2015-07-29 20:34:14.985000000',
 | 
			
		||||
          '2015-06-15 03:25:14.985000000',
 | 
			
		||||
          '06/15',
 | 
			
		||||
          '06/15 03:25',
 | 
			
		||||
          '06/15/15, 03:25:14', done);
 | 
			
		||||
          '06/15/15, 03:25:14');
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@@ -167,28 +165,28 @@ suite('gr-date-formatter tests', () => {
 | 
			
		||||
      return element._loadPreferences();
 | 
			
		||||
    }));
 | 
			
		||||
 | 
			
		||||
    test('Within 24 hours on same day', done => {
 | 
			
		||||
    test('Within 24 hours on same day', () => {
 | 
			
		||||
      testDates('2015-07-29 20:34:14.985000000',
 | 
			
		||||
          '2015-07-29 15:34:14.985000000',
 | 
			
		||||
          '15:34',
 | 
			
		||||
          '15:34',
 | 
			
		||||
          '2015-07-29, 15:34:14', done);
 | 
			
		||||
          '2015-07-29, 15:34:14');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Within 24 hours on different days', done => {
 | 
			
		||||
    test('Within 24 hours on different days', () => {
 | 
			
		||||
      testDates('2015-07-29 03:34:14.985000000',
 | 
			
		||||
          '2015-07-28 20:25:14.985000000',
 | 
			
		||||
          '07-28',
 | 
			
		||||
          '07-28 20:25',
 | 
			
		||||
          '2015-07-28, 20:25:14', done);
 | 
			
		||||
          '2015-07-28, 20:25:14');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('More than 24 hours but less than six months', done => {
 | 
			
		||||
    test('More than 24 hours but less than six months', () => {
 | 
			
		||||
      testDates('2015-07-29 20:34:14.985000000',
 | 
			
		||||
          '2015-06-15 03:25:14.985000000',
 | 
			
		||||
          '06-15',
 | 
			
		||||
          '06-15 03:25',
 | 
			
		||||
          '2015-06-15, 03:25:14', done);
 | 
			
		||||
          '2015-06-15, 03:25:14');
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@@ -203,28 +201,28 @@ suite('gr-date-formatter tests', () => {
 | 
			
		||||
      return element._loadPreferences();
 | 
			
		||||
    }));
 | 
			
		||||
 | 
			
		||||
    test('Within 24 hours on same day', done => {
 | 
			
		||||
    test('Within 24 hours on same day', () => {
 | 
			
		||||
      testDates('2015-07-29 20:34:14.985000000',
 | 
			
		||||
          '2015-07-29 15:34:14.985000000',
 | 
			
		||||
          '15:34',
 | 
			
		||||
          '15:34',
 | 
			
		||||
          '29.07.2015, 15:34:14', done);
 | 
			
		||||
          '29.07.2015, 15:34:14');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Within 24 hours on different days', done => {
 | 
			
		||||
    test('Within 24 hours on different days', () => {
 | 
			
		||||
      testDates('2015-07-29 03:34:14.985000000',
 | 
			
		||||
          '2015-07-28 20:25:14.985000000',
 | 
			
		||||
          '28. Jul',
 | 
			
		||||
          '28. Jul 20:25',
 | 
			
		||||
          '28.07.2015, 20:25:14', done);
 | 
			
		||||
          '28.07.2015, 20:25:14');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('More than 24 hours but less than six months', done => {
 | 
			
		||||
    test('More than 24 hours but less than six months', () => {
 | 
			
		||||
      testDates('2015-07-29 20:34:14.985000000',
 | 
			
		||||
          '2015-06-15 03:25:14.985000000',
 | 
			
		||||
          '15. Jun',
 | 
			
		||||
          '15. Jun 03:25',
 | 
			
		||||
          '15.06.2015, 03:25:14', done);
 | 
			
		||||
          '15.06.2015, 03:25:14');
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@@ -239,28 +237,28 @@ suite('gr-date-formatter tests', () => {
 | 
			
		||||
      return element._loadPreferences();
 | 
			
		||||
    }));
 | 
			
		||||
 | 
			
		||||
    test('Within 24 hours on same day', done => {
 | 
			
		||||
    test('Within 24 hours on same day', () => {
 | 
			
		||||
      testDates('2015-07-29 20:34:14.985000000',
 | 
			
		||||
          '2015-07-29 15:34:14.985000000',
 | 
			
		||||
          '15:34',
 | 
			
		||||
          '15:34',
 | 
			
		||||
          '29/07/2015, 15:34:14', done);
 | 
			
		||||
          '29/07/2015, 15:34:14');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Within 24 hours on different days', done => {
 | 
			
		||||
    test('Within 24 hours on different days', () => {
 | 
			
		||||
      testDates('2015-07-29 03:34:14.985000000',
 | 
			
		||||
          '2015-07-28 20:25:14.985000000',
 | 
			
		||||
          '28/07',
 | 
			
		||||
          '28/07 20:25',
 | 
			
		||||
          '28/07/2015, 20:25:14', done);
 | 
			
		||||
          '28/07/2015, 20:25:14');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('More than 24 hours but less than six months', done => {
 | 
			
		||||
    test('More than 24 hours but less than six months', () => {
 | 
			
		||||
      testDates('2015-07-29 20:34:14.985000000',
 | 
			
		||||
          '2015-06-15 03:25:14.985000000',
 | 
			
		||||
          '15/06',
 | 
			
		||||
          '15/06 03:25',
 | 
			
		||||
          '15/06/2015, 03:25:14', done);
 | 
			
		||||
          '15/06/2015, 03:25:14');
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@@ -276,12 +274,12 @@ suite('gr-date-formatter tests', () => {
 | 
			
		||||
      })
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    test('Within 24 hours on same day', done => {
 | 
			
		||||
    test('Within 24 hours on same day', () => {
 | 
			
		||||
      testDates('2015-07-29 20:34:14.985000000',
 | 
			
		||||
          '2015-07-29 15:34:14.985000000',
 | 
			
		||||
          '3:34 PM',
 | 
			
		||||
          '3:34 PM',
 | 
			
		||||
          'Jul 29, 2015, 3:34:14 PM', done);
 | 
			
		||||
          'Jul 29, 2015, 3:34:14 PM');
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@@ -297,12 +295,12 @@ suite('gr-date-formatter tests', () => {
 | 
			
		||||
      })
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    test('Within 24 hours on same day', done => {
 | 
			
		||||
    test('Within 24 hours on same day', () => {
 | 
			
		||||
      testDates('2015-07-29 20:34:14.985000000',
 | 
			
		||||
          '2015-07-29 15:34:14.985000000',
 | 
			
		||||
          '3:34 PM',
 | 
			
		||||
          '3:34 PM',
 | 
			
		||||
          '07/29/15, 3:34:14 PM', done);
 | 
			
		||||
          '07/29/15, 3:34:14 PM');
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@@ -318,12 +316,12 @@ suite('gr-date-formatter tests', () => {
 | 
			
		||||
      })
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    test('Within 24 hours on same day', done => {
 | 
			
		||||
    test('Within 24 hours on same day', () => {
 | 
			
		||||
      testDates('2015-07-29 20:34:14.985000000',
 | 
			
		||||
          '2015-07-29 15:34:14.985000000',
 | 
			
		||||
          '3:34 PM',
 | 
			
		||||
          '3:34 PM',
 | 
			
		||||
          '2015-07-29, 3:34:14 PM', done);
 | 
			
		||||
          '2015-07-29, 3:34:14 PM');
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@@ -339,12 +337,12 @@ suite('gr-date-formatter tests', () => {
 | 
			
		||||
      })
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    test('Within 24 hours on same day', done => {
 | 
			
		||||
    test('Within 24 hours on same day', () => {
 | 
			
		||||
      testDates('2015-07-29 20:34:14.985000000',
 | 
			
		||||
          '2015-07-29 15:34:14.985000000',
 | 
			
		||||
          '3:34 PM',
 | 
			
		||||
          '3:34 PM',
 | 
			
		||||
          '29.07.2015, 3:34:14 PM', done);
 | 
			
		||||
          '29.07.2015, 3:34:14 PM');
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@@ -360,12 +358,12 @@ suite('gr-date-formatter tests', () => {
 | 
			
		||||
      })
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    test('Within 24 hours on same day', done => {
 | 
			
		||||
    test('Within 24 hours on same day', () => {
 | 
			
		||||
      testDates('2015-07-29 20:34:14.985000000',
 | 
			
		||||
          '2015-07-29 15:34:14.985000000',
 | 
			
		||||
          '3:34 PM',
 | 
			
		||||
          '3:34 PM',
 | 
			
		||||
          '29/07/2015, 3:34:14 PM', done);
 | 
			
		||||
          '29/07/2015, 3:34:14 PM');
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@@ -380,20 +378,20 @@ suite('gr-date-formatter tests', () => {
 | 
			
		||||
      return element._loadPreferences();
 | 
			
		||||
    }));
 | 
			
		||||
 | 
			
		||||
    test('Within 24 hours on same day', done => {
 | 
			
		||||
    test('Within 24 hours on same day', () => {
 | 
			
		||||
      testDates('2015-07-29 20:34:14.985000000',
 | 
			
		||||
          '2015-07-29 15:34:14.985000000',
 | 
			
		||||
          '5 hours ago',
 | 
			
		||||
          '5 hours ago',
 | 
			
		||||
          'Jul 29, 2015, 3:34:14 PM', done);
 | 
			
		||||
          'Jul 29, 2015, 3:34:14 PM');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('More than six months', done => {
 | 
			
		||||
    test('More than six months', () => {
 | 
			
		||||
      testDates('2015-09-15 20:34:00.000000000',
 | 
			
		||||
          '2015-01-15 03:25:00.000000000',
 | 
			
		||||
          '8 months ago',
 | 
			
		||||
          '8 months ago',
 | 
			
		||||
          'Jan 15, 2015, 3:25:00 AM', done);
 | 
			
		||||
          'Jan 15, 2015, 3:25:00 AM');
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -28,35 +28,35 @@ suite('gr-dialog tests', () => {
 | 
			
		||||
    element = basicFixture.instantiate();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('events', done => {
 | 
			
		||||
    let numEvents = 0;
 | 
			
		||||
    function handler() { if (++numEvents == 2) { done(); } }
 | 
			
		||||
  test('events', () => {
 | 
			
		||||
    const confirm = sinon.stub();
 | 
			
		||||
    const cancel = sinon.stub();
 | 
			
		||||
    element.addEventListener('confirm', confirm);
 | 
			
		||||
    element.addEventListener('cancel', cancel);
 | 
			
		||||
 | 
			
		||||
    element.addEventListener('confirm', handler);
 | 
			
		||||
    element.addEventListener('cancel', handler);
 | 
			
		||||
    MockInteractions.tap(
 | 
			
		||||
        element.shadowRoot.querySelector('gr-button[primary]'));
 | 
			
		||||
    assert.equal(confirm.callCount, 1);
 | 
			
		||||
 | 
			
		||||
    MockInteractions.tap(element.shadowRoot
 | 
			
		||||
        .querySelector('gr-button[primary]'));
 | 
			
		||||
    MockInteractions.tap(element.shadowRoot
 | 
			
		||||
        .querySelector('gr-button:not([primary])'));
 | 
			
		||||
    MockInteractions.tap(
 | 
			
		||||
        element.shadowRoot.querySelector('gr-button:not([primary])'));
 | 
			
		||||
    assert.equal(cancel.callCount, 1);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('confirmOnEnter', () => {
 | 
			
		||||
    element.confirmOnEnter = false;
 | 
			
		||||
    const handleConfirmStub = sinon.stub(element, '_handleConfirm');
 | 
			
		||||
    const handleKeydownSpy = sinon.spy(element, '_handleKeydown');
 | 
			
		||||
    MockInteractions.pressAndReleaseKeyOn(element.shadowRoot
 | 
			
		||||
        .querySelector('main'),
 | 
			
		||||
    13, null, 'enter');
 | 
			
		||||
    MockInteractions.pressAndReleaseKeyOn(
 | 
			
		||||
        element.shadowRoot.querySelector('main'), 13, null, 'enter');
 | 
			
		||||
    flush();
 | 
			
		||||
 | 
			
		||||
    assert.isTrue(handleKeydownSpy.called);
 | 
			
		||||
    assert.isFalse(handleConfirmStub.called);
 | 
			
		||||
 | 
			
		||||
    element.confirmOnEnter = true;
 | 
			
		||||
    MockInteractions.pressAndReleaseKeyOn(element.shadowRoot
 | 
			
		||||
        .querySelector('main'),
 | 
			
		||||
    13, null, 'enter');
 | 
			
		||||
    MockInteractions.pressAndReleaseKeyOn(
 | 
			
		||||
        element.shadowRoot.querySelector('main'), 13, null, 'enter');
 | 
			
		||||
    flush();
 | 
			
		||||
 | 
			
		||||
    assert.isTrue(handleConfirmStub.called);
 | 
			
		||||
 
 | 
			
		||||
@@ -49,13 +49,12 @@ suite('gr-download-commands', () => {
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  suite('unauthenticated', () => {
 | 
			
		||||
    setup(done => {
 | 
			
		||||
    setup(async () => {
 | 
			
		||||
      element = basicFixture.instantiate();
 | 
			
		||||
      element.schemes = SCHEMES;
 | 
			
		||||
      element.commands = COMMANDS;
 | 
			
		||||
      element.selectedScheme = SELECTED_SCHEME;
 | 
			
		||||
      flush();
 | 
			
		||||
      flush(done);
 | 
			
		||||
      await flush();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('focusOnCopy', () => {
 | 
			
		||||
@@ -79,17 +78,16 @@ suite('gr-download-commands', () => {
 | 
			
		||||
          .querySelector('.commands')));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('tab selection', done => {
 | 
			
		||||
    test('tab selection', () => {
 | 
			
		||||
      assert.equal(element.$.downloadTabs.selected, '0');
 | 
			
		||||
      MockInteractions.tap(element.shadowRoot
 | 
			
		||||
          .querySelector('[data-scheme="ssh"]'));
 | 
			
		||||
      flush();
 | 
			
		||||
      assert.equal(element.selectedScheme, 'ssh');
 | 
			
		||||
      assert.equal(element.$.downloadTabs.selected, '2');
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('loads scheme from preferences', done => {
 | 
			
		||||
    test('loads scheme from preferences', () => {
 | 
			
		||||
      stub('gr-rest-api-interface', {
 | 
			
		||||
        getPreferences() {
 | 
			
		||||
          return Promise.resolve({download_scheme: 'repo'});
 | 
			
		||||
@@ -97,22 +95,20 @@ suite('gr-download-commands', () => {
 | 
			
		||||
      });
 | 
			
		||||
      element._loggedIn = true;
 | 
			
		||||
      assert.isTrue(element.$.restAPI.getPreferences.called);
 | 
			
		||||
      element.$.restAPI.getPreferences.lastCall.returnValue.then(() => {
 | 
			
		||||
      return element.$.restAPI.getPreferences.lastCall.returnValue.then(() => {
 | 
			
		||||
        assert.equal(element.selectedScheme, 'repo');
 | 
			
		||||
        done();
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('normalize scheme from preferences', done => {
 | 
			
		||||
    test('normalize scheme from preferences', () => {
 | 
			
		||||
      stub('gr-rest-api-interface', {
 | 
			
		||||
        getPreferences() {
 | 
			
		||||
          return Promise.resolve({download_scheme: 'REPO'});
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
      element._loggedIn = true;
 | 
			
		||||
      element.$.restAPI.getPreferences.lastCall.returnValue.then(() => {
 | 
			
		||||
      return element.$.restAPI.getPreferences.lastCall.returnValue.then(() => {
 | 
			
		||||
        assert.equal(element.selectedScheme, 'repo');
 | 
			
		||||
        done();
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -37,15 +37,13 @@ suite('gr-dropdown-list tests', () => {
 | 
			
		||||
    assert.isTrue(copyEl.hidden);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('show copy if enabled', done => {
 | 
			
		||||
  test('show copy if enabled', () => {
 | 
			
		||||
    element.showCopyForTriggerText = true;
 | 
			
		||||
    flush(() => {
 | 
			
		||||
      const copyEl = element.shadowRoot
 | 
			
		||||
          .querySelector('#triggerText + gr-copy-clipboard');
 | 
			
		||||
      assert.isTrue(!!copyEl);
 | 
			
		||||
      assert.isFalse(copyEl.hidden);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    flush();
 | 
			
		||||
    const copyEl = element.shadowRoot.querySelector(
 | 
			
		||||
        '#triggerText + gr-copy-clipboard');
 | 
			
		||||
    assert.isTrue(!!copyEl);
 | 
			
		||||
    assert.isFalse(copyEl.hidden);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('tap on trigger opens menu', () => {
 | 
			
		||||
@@ -66,7 +64,7 @@ suite('gr-dropdown-list tests', () => {
 | 
			
		||||
    assert.equal(element._computeMobileText(item), item.mobileText);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('options are selected and laid out correctly', done => {
 | 
			
		||||
  test('options are selected and laid out correctly', async () => {
 | 
			
		||||
    element.value = 2;
 | 
			
		||||
    element.items = [
 | 
			
		||||
      {
 | 
			
		||||
@@ -93,78 +91,77 @@ suite('gr-dropdown-list tests', () => {
 | 
			
		||||
    assert.equal(element.shadowRoot
 | 
			
		||||
        .querySelector('paper-listbox').selected, element.value);
 | 
			
		||||
    assert.equal(element.text, 'Button Text 2');
 | 
			
		||||
    flush(() => {
 | 
			
		||||
      const items = element.root.querySelectorAll('paper-item');
 | 
			
		||||
      const mobileItems = element.root.querySelectorAll('option');
 | 
			
		||||
      assert.equal(items.length, 3);
 | 
			
		||||
      assert.equal(mobileItems.length, 3);
 | 
			
		||||
    await flush();
 | 
			
		||||
 | 
			
		||||
      // First Item
 | 
			
		||||
      // The first item should be disabled, has no bottom text, and no date.
 | 
			
		||||
      assert.isFalse(!!items[0].disabled);
 | 
			
		||||
      assert.isFalse(mobileItems[0].disabled);
 | 
			
		||||
      assert.isFalse(items[0].classList.contains('iron-selected'));
 | 
			
		||||
      assert.isFalse(mobileItems[0].selected);
 | 
			
		||||
    const items = element.root.querySelectorAll('paper-item');
 | 
			
		||||
    const mobileItems = element.root.querySelectorAll('option');
 | 
			
		||||
    assert.equal(items.length, 3);
 | 
			
		||||
    assert.equal(mobileItems.length, 3);
 | 
			
		||||
 | 
			
		||||
      assert.isNotOk(items[0].querySelector('gr-date-formatter'));
 | 
			
		||||
      assert.isNotOk(items[0].querySelector('.bottomContent'));
 | 
			
		||||
      assert.equal(items[0].dataset.value, element.items[0].value);
 | 
			
		||||
      assert.equal(mobileItems[0].value, element.items[0].value);
 | 
			
		||||
      assert.equal(items[0].querySelector('.topContent div')
 | 
			
		||||
          .innerText, element.items[0].text);
 | 
			
		||||
    // First Item
 | 
			
		||||
    // The first item should be disabled, has no bottom text, and no date.
 | 
			
		||||
    assert.isFalse(!!items[0].disabled);
 | 
			
		||||
    assert.isFalse(mobileItems[0].disabled);
 | 
			
		||||
    assert.isFalse(items[0].classList.contains('iron-selected'));
 | 
			
		||||
    assert.isFalse(mobileItems[0].selected);
 | 
			
		||||
 | 
			
		||||
      // Since no mobile specific text, it should fall back to text.
 | 
			
		||||
      assert.equal(mobileItems[0].text, element.items[0].text);
 | 
			
		||||
    assert.isNotOk(items[0].querySelector('gr-date-formatter'));
 | 
			
		||||
    assert.isNotOk(items[0].querySelector('.bottomContent'));
 | 
			
		||||
    assert.equal(items[0].dataset.value, element.items[0].value);
 | 
			
		||||
    assert.equal(mobileItems[0].value, element.items[0].value);
 | 
			
		||||
    assert.equal(items[0].querySelector('.topContent div')
 | 
			
		||||
        .innerText, element.items[0].text);
 | 
			
		||||
 | 
			
		||||
      // Second Item
 | 
			
		||||
      // The second item should have top text, bottom text, and no date.
 | 
			
		||||
      assert.isFalse(!!items[1].disabled);
 | 
			
		||||
      assert.isFalse(mobileItems[1].disabled);
 | 
			
		||||
      assert.isTrue(items[1].classList.contains('iron-selected'));
 | 
			
		||||
      assert.isTrue(mobileItems[1].selected);
 | 
			
		||||
    // Since no mobile specific text, it should fall back to text.
 | 
			
		||||
    assert.equal(mobileItems[0].text, element.items[0].text);
 | 
			
		||||
 | 
			
		||||
      assert.isNotOk(items[1].querySelector('gr-date-formatter'));
 | 
			
		||||
      assert.isOk(items[1].querySelector('.bottomContent'));
 | 
			
		||||
      assert.equal(items[1].dataset.value, element.items[1].value);
 | 
			
		||||
      assert.equal(mobileItems[1].value, element.items[1].value);
 | 
			
		||||
      assert.equal(items[1].querySelector('.topContent div')
 | 
			
		||||
          .innerText, element.items[1].text);
 | 
			
		||||
    // Second Item
 | 
			
		||||
    // The second item should have top text, bottom text, and no date.
 | 
			
		||||
    assert.isFalse(!!items[1].disabled);
 | 
			
		||||
    assert.isFalse(mobileItems[1].disabled);
 | 
			
		||||
    assert.isTrue(items[1].classList.contains('iron-selected'));
 | 
			
		||||
    assert.isTrue(mobileItems[1].selected);
 | 
			
		||||
 | 
			
		||||
      // Since there is mobile specific text, it should that.
 | 
			
		||||
      assert.equal(mobileItems[1].text, element.items[1].mobileText);
 | 
			
		||||
    assert.isNotOk(items[1].querySelector('gr-date-formatter'));
 | 
			
		||||
    assert.isOk(items[1].querySelector('.bottomContent'));
 | 
			
		||||
    assert.equal(items[1].dataset.value, element.items[1].value);
 | 
			
		||||
    assert.equal(mobileItems[1].value, element.items[1].value);
 | 
			
		||||
    assert.equal(items[1].querySelector('.topContent div')
 | 
			
		||||
        .innerText, element.items[1].text);
 | 
			
		||||
 | 
			
		||||
      // Since this item is selected, and it has triggerText defined, that
 | 
			
		||||
      // should be used.
 | 
			
		||||
      assert.equal(element.text, element.items[1].triggerText);
 | 
			
		||||
    // Since there is mobile specific text, it should that.
 | 
			
		||||
    assert.equal(mobileItems[1].text, element.items[1].mobileText);
 | 
			
		||||
 | 
			
		||||
      // Third item
 | 
			
		||||
      // The third item should be disabled, and have a date, and bottom content.
 | 
			
		||||
      assert.isTrue(!!items[2].disabled);
 | 
			
		||||
      assert.isTrue(mobileItems[2].disabled);
 | 
			
		||||
      assert.isFalse(items[2].classList.contains('iron-selected'));
 | 
			
		||||
      assert.isFalse(mobileItems[2].selected);
 | 
			
		||||
    // Since this item is selected, and it has triggerText defined, that
 | 
			
		||||
    // should be used.
 | 
			
		||||
    assert.equal(element.text, element.items[1].triggerText);
 | 
			
		||||
 | 
			
		||||
      assert.isOk(items[2].querySelector('gr-date-formatter'));
 | 
			
		||||
      assert.isOk(items[2].querySelector('.bottomContent'));
 | 
			
		||||
      assert.equal(items[2].dataset.value, element.items[2].value);
 | 
			
		||||
      assert.equal(mobileItems[2].value, element.items[2].value);
 | 
			
		||||
      assert.equal(items[2].querySelector('.topContent div')
 | 
			
		||||
          .innerText, element.items[2].text);
 | 
			
		||||
    // Third item
 | 
			
		||||
    // The third item should be disabled, and have a date, and bottom content.
 | 
			
		||||
    assert.isTrue(!!items[2].disabled);
 | 
			
		||||
    assert.isTrue(mobileItems[2].disabled);
 | 
			
		||||
    assert.isFalse(items[2].classList.contains('iron-selected'));
 | 
			
		||||
    assert.isFalse(mobileItems[2].selected);
 | 
			
		||||
 | 
			
		||||
      // Since there is mobile specific text, it should that.
 | 
			
		||||
      assert.equal(mobileItems[2].text, element.items[2].mobileText);
 | 
			
		||||
    assert.isOk(items[2].querySelector('gr-date-formatter'));
 | 
			
		||||
    assert.isOk(items[2].querySelector('.bottomContent'));
 | 
			
		||||
    assert.equal(items[2].dataset.value, element.items[2].value);
 | 
			
		||||
    assert.equal(mobileItems[2].value, element.items[2].value);
 | 
			
		||||
    assert.equal(items[2].querySelector('.topContent div')
 | 
			
		||||
        .innerText, element.items[2].text);
 | 
			
		||||
 | 
			
		||||
      // Select a new item.
 | 
			
		||||
      MockInteractions.tap(items[0]);
 | 
			
		||||
      flush();
 | 
			
		||||
      assert.equal(element.value, 1);
 | 
			
		||||
      assert.isTrue(items[0].classList.contains('iron-selected'));
 | 
			
		||||
      assert.isTrue(mobileItems[0].selected);
 | 
			
		||||
    // Since there is mobile specific text, it should that.
 | 
			
		||||
    assert.equal(mobileItems[2].text, element.items[2].mobileText);
 | 
			
		||||
 | 
			
		||||
      // Since no triggerText, the fallback is used.
 | 
			
		||||
      assert.equal(element.text, element.items[0].text);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    // Select a new item.
 | 
			
		||||
    MockInteractions.tap(items[0]);
 | 
			
		||||
    flush();
 | 
			
		||||
    assert.equal(element.value, 1);
 | 
			
		||||
    assert.isTrue(items[0].classList.contains('iron-selected'));
 | 
			
		||||
    assert.isTrue(mobileItems[0].selected);
 | 
			
		||||
 | 
			
		||||
    // Since no triggerText, the fallback is used.
 | 
			
		||||
    assert.equal(element.text, element.items[0].text);
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -27,23 +27,27 @@ suite('gr-editable-content tests', () => {
 | 
			
		||||
    element = basicFixture.instantiate();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('save event', done => {
 | 
			
		||||
  test('save event', () => {
 | 
			
		||||
    element.content = '';
 | 
			
		||||
    element._newContent = 'foo';
 | 
			
		||||
    element.addEventListener('editable-content-save', e => {
 | 
			
		||||
      assert.equal(e.detail.content, 'foo');
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    const handler = sinon.spy();
 | 
			
		||||
    element.addEventListener('editable-content-save', handler);
 | 
			
		||||
 | 
			
		||||
    MockInteractions.tap(element.shadowRoot
 | 
			
		||||
        .querySelector('gr-button[primary]'));
 | 
			
		||||
 | 
			
		||||
    assert.isTrue(handler.called);
 | 
			
		||||
    assert.equal(handler.lastCall.args[0].detail.content, 'foo');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('cancel event', done => {
 | 
			
		||||
    element.addEventListener('editable-content-cancel', () => {
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  test('cancel event', () => {
 | 
			
		||||
    const handler = sinon.spy();
 | 
			
		||||
    element.addEventListener('editable-content-cancel', handler);
 | 
			
		||||
 | 
			
		||||
    MockInteractions.tap(element.shadowRoot
 | 
			
		||||
        .querySelector('gr-button:not([primary])'));
 | 
			
		||||
 | 
			
		||||
    assert.isTrue(handler.called);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('enabling editing keeps old content', () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,6 @@
 | 
			
		||||
 | 
			
		||||
import '../../../test/common-test-setup-karma.js';
 | 
			
		||||
import './gr-editable-label.js';
 | 
			
		||||
import {flush as flush$0} from '@polymer/polymer/lib/legacy/polymer.dom.js';
 | 
			
		||||
import {html} from '@polymer/polymer/lib/utils/html-tag.js';
 | 
			
		||||
 | 
			
		||||
const basicFixture = fixtureFromTemplate(html`
 | 
			
		||||
@@ -71,126 +70,106 @@ suite('gr-editable-label tests', () => {
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('title with placeholder', done => {
 | 
			
		||||
  test('title with placeholder', () => {
 | 
			
		||||
    assert.equal(element.title, 'value text');
 | 
			
		||||
    element.value = '';
 | 
			
		||||
 | 
			
		||||
    element.async(() => {
 | 
			
		||||
      assert.equal(element.title, 'label text');
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    flush();
 | 
			
		||||
    assert.equal(element.title, 'label text');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('title without placeholder', done => {
 | 
			
		||||
  test('title without placeholder', () => {
 | 
			
		||||
    assert.equal(elementNoPlaceholder.title, '');
 | 
			
		||||
    element.value = 'value text';
 | 
			
		||||
 | 
			
		||||
    element.async(() => {
 | 
			
		||||
      assert.equal(element.title, 'value text');
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    flush();
 | 
			
		||||
    assert.equal(element.title, 'value text');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('edit value', done => {
 | 
			
		||||
    const editedStub = sinon.stub();
 | 
			
		||||
    element.addEventListener('changed', editedStub);
 | 
			
		||||
  test('edit value', async () => {
 | 
			
		||||
    const editedSpy = sinon.spy();
 | 
			
		||||
    element.addEventListener('changed', editedSpy);
 | 
			
		||||
    assert.isFalse(element.editing);
 | 
			
		||||
 | 
			
		||||
    MockInteractions.tap(label);
 | 
			
		||||
 | 
			
		||||
    flush$0();
 | 
			
		||||
    flush();
 | 
			
		||||
 | 
			
		||||
    assert.isTrue(element.editing);
 | 
			
		||||
    assert.isFalse(editedSpy.called);
 | 
			
		||||
 | 
			
		||||
    element._inputText = 'new text';
 | 
			
		||||
 | 
			
		||||
    assert.isFalse(editedStub.called);
 | 
			
		||||
 | 
			
		||||
    element.async(() => {
 | 
			
		||||
      assert.isTrue(editedStub.called);
 | 
			
		||||
      assert.equal(input.value, 'new text');
 | 
			
		||||
      assert.isFalse(element.editing);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // Press enter:
 | 
			
		||||
    MockInteractions.keyDownOn(input, 13);
 | 
			
		||||
    flush();
 | 
			
		||||
 | 
			
		||||
    assert.isTrue(editedSpy.called);
 | 
			
		||||
    assert.equal(input.value, 'new text');
 | 
			
		||||
    assert.isFalse(element.editing);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('save button', done => {
 | 
			
		||||
    const editedStub = sinon.stub();
 | 
			
		||||
    element.addEventListener('changed', editedStub);
 | 
			
		||||
  test('save button', () => {
 | 
			
		||||
    const editedSpy = sinon.spy();
 | 
			
		||||
    element.addEventListener('changed', editedSpy);
 | 
			
		||||
    assert.isFalse(element.editing);
 | 
			
		||||
 | 
			
		||||
    MockInteractions.tap(label);
 | 
			
		||||
 | 
			
		||||
    flush$0();
 | 
			
		||||
    flush();
 | 
			
		||||
 | 
			
		||||
    assert.isTrue(element.editing);
 | 
			
		||||
    assert.isFalse(editedSpy.called);
 | 
			
		||||
 | 
			
		||||
    element._inputText = 'new text';
 | 
			
		||||
 | 
			
		||||
    assert.isFalse(editedStub.called);
 | 
			
		||||
 | 
			
		||||
    element.async(() => {
 | 
			
		||||
      assert.isTrue(editedStub.called);
 | 
			
		||||
      assert.equal(input.value, 'new text');
 | 
			
		||||
      assert.isFalse(element.editing);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // Press enter:
 | 
			
		||||
    MockInteractions.tap(element.$.saveBtn, 13);
 | 
			
		||||
    flush();
 | 
			
		||||
 | 
			
		||||
    assert.isTrue(editedSpy.called);
 | 
			
		||||
    assert.equal(input.value, 'new text');
 | 
			
		||||
    assert.isFalse(element.editing);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('edit and then escape key', done => {
 | 
			
		||||
    const editedStub = sinon.stub();
 | 
			
		||||
    element.addEventListener('changed', editedStub);
 | 
			
		||||
  test('edit and then escape key', () => {
 | 
			
		||||
    const editedSpy = sinon.spy();
 | 
			
		||||
    element.addEventListener('changed', editedSpy);
 | 
			
		||||
    assert.isFalse(element.editing);
 | 
			
		||||
 | 
			
		||||
    MockInteractions.tap(label);
 | 
			
		||||
 | 
			
		||||
    flush$0();
 | 
			
		||||
    flush();
 | 
			
		||||
 | 
			
		||||
    assert.isTrue(element.editing);
 | 
			
		||||
    assert.isFalse(editedSpy.called);
 | 
			
		||||
 | 
			
		||||
    element._inputText = 'new text';
 | 
			
		||||
 | 
			
		||||
    assert.isFalse(editedStub.called);
 | 
			
		||||
 | 
			
		||||
    element.async(() => {
 | 
			
		||||
      assert.isFalse(editedStub.called);
 | 
			
		||||
      // Text changes should be discarded.
 | 
			
		||||
      assert.equal(input.value, 'value text');
 | 
			
		||||
      assert.isFalse(element.editing);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // Press escape:
 | 
			
		||||
    MockInteractions.keyDownOn(input, 27);
 | 
			
		||||
    flush();
 | 
			
		||||
 | 
			
		||||
    assert.isFalse(editedSpy.called);
 | 
			
		||||
    // Text changes should be discarded.
 | 
			
		||||
    assert.equal(input.value, 'value text');
 | 
			
		||||
    assert.isFalse(element.editing);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('cancel button', done => {
 | 
			
		||||
    const editedStub = sinon.stub();
 | 
			
		||||
    element.addEventListener('changed', editedStub);
 | 
			
		||||
  test('cancel button', () => {
 | 
			
		||||
    const editedSpy = sinon.spy();
 | 
			
		||||
    element.addEventListener('changed', editedSpy);
 | 
			
		||||
    assert.isFalse(element.editing);
 | 
			
		||||
 | 
			
		||||
    MockInteractions.tap(label);
 | 
			
		||||
 | 
			
		||||
    flush$0();
 | 
			
		||||
    flush();
 | 
			
		||||
 | 
			
		||||
    assert.isTrue(element.editing);
 | 
			
		||||
    assert.isFalse(editedSpy.called);
 | 
			
		||||
 | 
			
		||||
    element._inputText = 'new text';
 | 
			
		||||
 | 
			
		||||
    assert.isFalse(editedStub.called);
 | 
			
		||||
 | 
			
		||||
    element.async(() => {
 | 
			
		||||
      assert.isFalse(editedStub.called);
 | 
			
		||||
      // Text changes should be discarded.
 | 
			
		||||
      assert.equal(input.value, 'value text');
 | 
			
		||||
      assert.isFalse(element.editing);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // Press escape:
 | 
			
		||||
    MockInteractions.tap(element.$.cancelBtn);
 | 
			
		||||
    flush();
 | 
			
		||||
 | 
			
		||||
    assert.isFalse(editedSpy.called);
 | 
			
		||||
    // Text changes should be discarded.
 | 
			
		||||
    assert.equal(input.value, 'value text');
 | 
			
		||||
    assert.isFalse(element.editing);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  suite('gr-editable-label read-only tests', () => {
 | 
			
		||||
@@ -208,7 +187,7 @@ suite('gr-editable-label tests', () => {
 | 
			
		||||
      assert.isFalse(element.$.dropdown.opened);
 | 
			
		||||
      MockInteractions.tap(label);
 | 
			
		||||
 | 
			
		||||
      flush$0();
 | 
			
		||||
      flush();
 | 
			
		||||
 | 
			
		||||
      // The dropdown is still closed.
 | 
			
		||||
      assert.isFalse(element.$.dropdown.opened);
 | 
			
		||||
 
 | 
			
		||||
@@ -112,7 +112,7 @@ suite('gr-hovercard-account tests', () => {
 | 
			
		||||
        element.voteableText);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('add to attention set', done => {
 | 
			
		||||
  test('add to attention set', async () => {
 | 
			
		||||
    let apiResolve;
 | 
			
		||||
    const apiPromise = new Promise(r => {
 | 
			
		||||
      apiResolve = r;
 | 
			
		||||
@@ -140,13 +140,12 @@ suite('gr-hovercard-account tests', () => {
 | 
			
		||||
    assert.isFalse(element._isShowing, 'hovercard is hidden');
 | 
			
		||||
 | 
			
		||||
    apiResolve({});
 | 
			
		||||
    flush(() => {
 | 
			
		||||
      assert.isTrue(hideAlertListener.called, 'hideAlertListener was called');
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    await flush();
 | 
			
		||||
 | 
			
		||||
    assert.isTrue(hideAlertListener.called, 'hideAlertListener was called');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('remove from attention set', done => {
 | 
			
		||||
  test('remove from attention set', async () => {
 | 
			
		||||
    let apiResolve;
 | 
			
		||||
    const apiPromise = new Promise(r => {
 | 
			
		||||
      apiResolve = r;
 | 
			
		||||
@@ -175,10 +174,9 @@ suite('gr-hovercard-account tests', () => {
 | 
			
		||||
    assert.isFalse(element._isShowing, 'hovercard is hidden');
 | 
			
		||||
 | 
			
		||||
    apiResolve({});
 | 
			
		||||
    flush(() => {
 | 
			
		||||
      assert.isTrue(hideAlertListener.called, 'hideAlertListener was called');
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    await flush();
 | 
			
		||||
 | 
			
		||||
    assert.isTrue(hideAlertListener.called, 'hideAlertListener was called');
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -27,8 +27,12 @@ suite('gr-hovercard tests', () => {
 | 
			
		||||
  let element;
 | 
			
		||||
 | 
			
		||||
  let button;
 | 
			
		||||
  let testResolve;
 | 
			
		||||
  let testPromise;
 | 
			
		||||
 | 
			
		||||
  setup(() => {
 | 
			
		||||
    testResolve = undefined;
 | 
			
		||||
    testPromise = new Promise(r => testResolve = r);
 | 
			
		||||
    button = document.createElement('button');
 | 
			
		||||
    button.innerHTML = 'Hello';
 | 
			
		||||
    button.setAttribute('id', 'foo');
 | 
			
		||||
@@ -89,66 +93,74 @@ suite('gr-hovercard tests', () => {
 | 
			
		||||
    assert.equal(style.visibility, 'visible');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('debounceShow does not show immediately', done => {
 | 
			
		||||
  test('debounceShow does not show immediately', async () => {
 | 
			
		||||
    element.debounceShowBy(100);
 | 
			
		||||
    setTimeout(() => {
 | 
			
		||||
      assert.isFalse(element._isShowing);
 | 
			
		||||
      done();
 | 
			
		||||
    }, 0);
 | 
			
		||||
    setTimeout(testResolve, 0);
 | 
			
		||||
    await testPromise;
 | 
			
		||||
    assert.isFalse(element._isShowing);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('debounceShow shows after delay', done => {
 | 
			
		||||
  test('debounceShow shows after delay', async () => {
 | 
			
		||||
    element.debounceShowBy(1);
 | 
			
		||||
    setTimeout(() => {
 | 
			
		||||
      assert.isTrue(element._isShowing);
 | 
			
		||||
      done();
 | 
			
		||||
    }, 10);
 | 
			
		||||
    setTimeout(testResolve, 10);
 | 
			
		||||
    await testPromise;
 | 
			
		||||
    assert.isTrue(element._isShowing);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('card is scheduled to show on enter and hides on leave', done => {
 | 
			
		||||
  test('card is scheduled to show on enter and hides on leave', async () => {
 | 
			
		||||
    const button = document.querySelector('button');
 | 
			
		||||
    let enterResolve = undefined;
 | 
			
		||||
    const enterPromise = new Promise(r => enterResolve = r);
 | 
			
		||||
    button.addEventListener('mouseenter', enterResolve);
 | 
			
		||||
    let leaveResolve = undefined;
 | 
			
		||||
    const leavePromise = new Promise(r => leaveResolve = r);
 | 
			
		||||
    button.addEventListener('mouseleave', leaveResolve);
 | 
			
		||||
 | 
			
		||||
    assert.isFalse(element._isShowing);
 | 
			
		||||
    const enterHandler = event => {
 | 
			
		||||
      assert.isTrue(element._isScheduledToShow);
 | 
			
		||||
      element._showDebouncer.flush();
 | 
			
		||||
      assert.isTrue(element._isShowing);
 | 
			
		||||
      assert.isFalse(element._isScheduledToShow);
 | 
			
		||||
      button.dispatchEvent(new CustomEvent('mouseleave'));
 | 
			
		||||
    };
 | 
			
		||||
    const leaveHandler = event => {
 | 
			
		||||
      assert.isTrue(element._isScheduledToHide);
 | 
			
		||||
      assert.isTrue(element._isShowing);
 | 
			
		||||
      element._hideDebouncer.flush();
 | 
			
		||||
      assert.isFalse(element._isScheduledToShow);
 | 
			
		||||
      assert.isFalse(element._isShowing);
 | 
			
		||||
      button.removeEventListener('mouseenter', enterHandler);
 | 
			
		||||
      button.removeEventListener('mouseleave', leaveHandler);
 | 
			
		||||
      done();
 | 
			
		||||
    };
 | 
			
		||||
    button.addEventListener('mouseenter', enterHandler);
 | 
			
		||||
    button.addEventListener('mouseleave', leaveHandler);
 | 
			
		||||
    button.dispatchEvent(new CustomEvent('mouseenter'));
 | 
			
		||||
 | 
			
		||||
    await enterPromise;
 | 
			
		||||
    assert.isTrue(element._isScheduledToShow);
 | 
			
		||||
    element._showDebouncer.flush();
 | 
			
		||||
    assert.isTrue(element._isShowing);
 | 
			
		||||
    assert.isFalse(element._isScheduledToShow);
 | 
			
		||||
 | 
			
		||||
    button.dispatchEvent(new CustomEvent('mouseleave'));
 | 
			
		||||
 | 
			
		||||
    await leavePromise;
 | 
			
		||||
    assert.isTrue(element._isScheduledToHide);
 | 
			
		||||
    assert.isTrue(element._isShowing);
 | 
			
		||||
    element._hideDebouncer.flush();
 | 
			
		||||
    assert.isFalse(element._isScheduledToShow);
 | 
			
		||||
    assert.isFalse(element._isShowing);
 | 
			
		||||
 | 
			
		||||
    button.removeEventListener('mouseenter', enterResolve);
 | 
			
		||||
    button.removeEventListener('mouseleave', leaveResolve);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('card should disappear on click', done => {
 | 
			
		||||
  test('card should disappear on click', async () => {
 | 
			
		||||
    const button = document.querySelector('button');
 | 
			
		||||
    let enterResolve = undefined;
 | 
			
		||||
    const enterPromise = new Promise(r => enterResolve = r);
 | 
			
		||||
    button.addEventListener('mouseenter', enterResolve);
 | 
			
		||||
    let clickResolve = undefined;
 | 
			
		||||
    const clickPromise = new Promise(r => clickResolve = r);
 | 
			
		||||
    button.addEventListener('click', clickResolve);
 | 
			
		||||
 | 
			
		||||
    assert.isFalse(element._isShowing);
 | 
			
		||||
    const enterHandler = event => {
 | 
			
		||||
      assert.isTrue(element._isScheduledToShow);
 | 
			
		||||
      // click to hide
 | 
			
		||||
      MockInteractions.tap(button);
 | 
			
		||||
    };
 | 
			
		||||
    const leaveHandler = event => {
 | 
			
		||||
      // no flush needed as hide will be called immediately
 | 
			
		||||
      assert.isFalse(element._isScheduledToShow);
 | 
			
		||||
      assert.isFalse(element._isShowing);
 | 
			
		||||
      button.removeEventListener('mouseenter', enterHandler);
 | 
			
		||||
      button.removeEventListener('click', leaveHandler);
 | 
			
		||||
      done();
 | 
			
		||||
    };
 | 
			
		||||
    button.addEventListener('mouseenter', enterHandler);
 | 
			
		||||
    button.addEventListener('click', leaveHandler);
 | 
			
		||||
 | 
			
		||||
    button.dispatchEvent(new CustomEvent('mouseenter'));
 | 
			
		||||
 | 
			
		||||
    await enterPromise;
 | 
			
		||||
    assert.isTrue(element._isScheduledToShow);
 | 
			
		||||
    MockInteractions.tap(button);
 | 
			
		||||
 | 
			
		||||
    await clickPromise;
 | 
			
		||||
    assert.isFalse(element._isScheduledToShow);
 | 
			
		||||
    assert.isFalse(element._isShowing);
 | 
			
		||||
 | 
			
		||||
    button.removeEventListener('mouseenter', enterResolve);
 | 
			
		||||
    button.removeEventListener('click', clickResolve);
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -107,106 +107,91 @@ suite('gr-change-actions-js-api-interface tests', () => {
 | 
			
		||||
      assertArraysEqual(element.primaryActionKeys, []);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('action buttons', done => {
 | 
			
		||||
    test('action buttons', () => {
 | 
			
		||||
      const key = changeActions.add(changeActions.ActionType.REVISION, 'Bork!');
 | 
			
		||||
      const handler = sinon.spy();
 | 
			
		||||
      changeActions.addTapListener(key, handler);
 | 
			
		||||
      flush(() => {
 | 
			
		||||
        MockInteractions.tap(element.shadowRoot
 | 
			
		||||
            .querySelector('[data-action-key="' + key + '"]'));
 | 
			
		||||
        assert(handler.calledOnce);
 | 
			
		||||
        changeActions.removeTapListener(key, handler);
 | 
			
		||||
        MockInteractions.tap(element.shadowRoot
 | 
			
		||||
            .querySelector('[data-action-key="' + key + '"]'));
 | 
			
		||||
        assert(handler.calledOnce);
 | 
			
		||||
        changeActions.remove(key);
 | 
			
		||||
        flush(() => {
 | 
			
		||||
          assert.isNull(element.shadowRoot
 | 
			
		||||
              .querySelector('[data-action-key="' + key + '"]'));
 | 
			
		||||
          done();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
      flush();
 | 
			
		||||
      MockInteractions.tap(element.shadowRoot
 | 
			
		||||
          .querySelector('[data-action-key="' + key + '"]'));
 | 
			
		||||
      assert(handler.calledOnce);
 | 
			
		||||
      changeActions.removeTapListener(key, handler);
 | 
			
		||||
      MockInteractions.tap(element.shadowRoot
 | 
			
		||||
          .querySelector('[data-action-key="' + key + '"]'));
 | 
			
		||||
      assert(handler.calledOnce);
 | 
			
		||||
      changeActions.remove(key);
 | 
			
		||||
      flush();
 | 
			
		||||
      assert.isNull(element.shadowRoot
 | 
			
		||||
          .querySelector('[data-action-key="' + key + '"]'));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('action button properties', done => {
 | 
			
		||||
    test('action button properties', () => {
 | 
			
		||||
      const key = changeActions.add(changeActions.ActionType.REVISION, 'Bork!');
 | 
			
		||||
      flush(() => {
 | 
			
		||||
        const button = element.shadowRoot
 | 
			
		||||
            .querySelector('[data-action-key="' + key + '"]');
 | 
			
		||||
        assert.isOk(button);
 | 
			
		||||
        assert.equal(button.getAttribute('data-label'), 'Bork!');
 | 
			
		||||
        assert.isNotOk(button.disabled);
 | 
			
		||||
        changeActions.setLabel(key, 'Yo');
 | 
			
		||||
        changeActions.setTitle(key, 'Yo hint');
 | 
			
		||||
        changeActions.setEnabled(key, false);
 | 
			
		||||
        changeActions.setIcon(key, 'pupper');
 | 
			
		||||
        flush(() => {
 | 
			
		||||
          assert.equal(button.getAttribute('data-label'), 'Yo');
 | 
			
		||||
          assert.equal(button.getAttribute('title'), 'Yo hint');
 | 
			
		||||
          assert.isTrue(button.disabled);
 | 
			
		||||
          assert.equal(button.querySelector('iron-icon').icon,
 | 
			
		||||
              'gr-icons:pupper');
 | 
			
		||||
          done();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
      flush();
 | 
			
		||||
      const button = element.shadowRoot
 | 
			
		||||
          .querySelector('[data-action-key="' + key + '"]');
 | 
			
		||||
      assert.isOk(button);
 | 
			
		||||
      assert.equal(button.getAttribute('data-label'), 'Bork!');
 | 
			
		||||
      assert.isNotOk(button.disabled);
 | 
			
		||||
      changeActions.setLabel(key, 'Yo');
 | 
			
		||||
      changeActions.setTitle(key, 'Yo hint');
 | 
			
		||||
      changeActions.setEnabled(key, false);
 | 
			
		||||
      changeActions.setIcon(key, 'pupper');
 | 
			
		||||
      flush();
 | 
			
		||||
      assert.equal(button.getAttribute('data-label'), 'Yo');
 | 
			
		||||
      assert.equal(button.getAttribute('title'), 'Yo hint');
 | 
			
		||||
      assert.isTrue(button.disabled);
 | 
			
		||||
      assert.equal(button.querySelector('iron-icon').icon,
 | 
			
		||||
          'gr-icons:pupper');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('hide action buttons', done => {
 | 
			
		||||
    test('hide action buttons', () => {
 | 
			
		||||
      const key = changeActions.add(changeActions.ActionType.REVISION, 'Bork!');
 | 
			
		||||
      flush(() => {
 | 
			
		||||
        const button = element.shadowRoot
 | 
			
		||||
            .querySelector('[data-action-key="' + key + '"]');
 | 
			
		||||
        assert.isOk(button);
 | 
			
		||||
        assert.isFalse(button.hasAttribute('hidden'));
 | 
			
		||||
        changeActions.setActionHidden(
 | 
			
		||||
            changeActions.ActionType.REVISION, key, true);
 | 
			
		||||
        flush(() => {
 | 
			
		||||
          const button = element.shadowRoot
 | 
			
		||||
              .querySelector('[data-action-key="' + key + '"]');
 | 
			
		||||
          assert.isNotOk(button);
 | 
			
		||||
          done();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
      flush();
 | 
			
		||||
      let button = element.shadowRoot
 | 
			
		||||
          .querySelector('[data-action-key="' + key + '"]');
 | 
			
		||||
      assert.isOk(button);
 | 
			
		||||
      assert.isFalse(button.hasAttribute('hidden'));
 | 
			
		||||
      changeActions.setActionHidden(
 | 
			
		||||
          changeActions.ActionType.REVISION, key, true);
 | 
			
		||||
      flush();
 | 
			
		||||
      button = element.shadowRoot
 | 
			
		||||
          .querySelector('[data-action-key="' + key + '"]');
 | 
			
		||||
      assert.isNotOk(button);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('move action button to overflow', done => {
 | 
			
		||||
    test('move action button to overflow', async () => {
 | 
			
		||||
      const key = changeActions.add(changeActions.ActionType.REVISION, 'Bork!');
 | 
			
		||||
      flush(() => {
 | 
			
		||||
        assert.isTrue(element.$.moreActions.hidden);
 | 
			
		||||
        assert.isOk(element.shadowRoot
 | 
			
		||||
            .querySelector('[data-action-key="' + key + '"]'));
 | 
			
		||||
        changeActions.setActionOverflow(
 | 
			
		||||
            changeActions.ActionType.REVISION, key, true);
 | 
			
		||||
        flush(() => {
 | 
			
		||||
          assert.isNotOk(element.shadowRoot
 | 
			
		||||
              .querySelector('[data-action-key="' + key + '"]'));
 | 
			
		||||
          assert.isFalse(element.$.moreActions.hidden);
 | 
			
		||||
          assert.strictEqual(element.$.moreActions.items[0].name, 'Bork!');
 | 
			
		||||
          done();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
      await flush();
 | 
			
		||||
      assert.isTrue(element.$.moreActions.hidden);
 | 
			
		||||
      assert.isOk(element.shadowRoot
 | 
			
		||||
          .querySelector('[data-action-key="' + key + '"]'));
 | 
			
		||||
      changeActions.setActionOverflow(
 | 
			
		||||
          changeActions.ActionType.REVISION, key, true);
 | 
			
		||||
      flush();
 | 
			
		||||
      assert.isNotOk(element.shadowRoot
 | 
			
		||||
          .querySelector('[data-action-key="' + key + '"]'));
 | 
			
		||||
      assert.isFalse(element.$.moreActions.hidden);
 | 
			
		||||
      assert.strictEqual(element.$.moreActions.items[0].name, 'Bork!');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('change actions priority', done => {
 | 
			
		||||
    test('change actions priority', () => {
 | 
			
		||||
      const key1 =
 | 
			
		||||
        changeActions.add(changeActions.ActionType.REVISION, 'Bork!');
 | 
			
		||||
      const key2 =
 | 
			
		||||
        changeActions.add(changeActions.ActionType.CHANGE, 'Squanch?');
 | 
			
		||||
      flush(() => {
 | 
			
		||||
        let buttons =
 | 
			
		||||
          element.root.querySelectorAll('[data-action-key]');
 | 
			
		||||
        assert.equal(buttons[0].getAttribute('data-action-key'), key1);
 | 
			
		||||
        assert.equal(buttons[1].getAttribute('data-action-key'), key2);
 | 
			
		||||
        changeActions.setActionPriority(
 | 
			
		||||
            changeActions.ActionType.REVISION, key1, 10);
 | 
			
		||||
        flush(() => {
 | 
			
		||||
          buttons =
 | 
			
		||||
            element.root.querySelectorAll('[data-action-key]');
 | 
			
		||||
          assert.equal(buttons[0].getAttribute('data-action-key'), key2);
 | 
			
		||||
          assert.equal(buttons[1].getAttribute('data-action-key'), key1);
 | 
			
		||||
          done();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
      flush();
 | 
			
		||||
      let buttons =
 | 
			
		||||
        element.root.querySelectorAll('[data-action-key]');
 | 
			
		||||
      assert.equal(buttons[0].getAttribute('data-action-key'), key1);
 | 
			
		||||
      assert.equal(buttons[1].getAttribute('data-action-key'), key2);
 | 
			
		||||
      changeActions.setActionPriority(
 | 
			
		||||
          changeActions.ActionType.REVISION, key1, 10);
 | 
			
		||||
      flush();
 | 
			
		||||
      buttons =
 | 
			
		||||
        element.root.querySelectorAll('[data-action-key]');
 | 
			
		||||
      assert.equal(buttons[0].getAttribute('data-action-key'), key2);
 | 
			
		||||
      assert.equal(buttons[1].getAttribute('data-action-key'), key1);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -182,18 +182,20 @@ suite('gr-js-api-interface tests', () => {
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('history event', done => {
 | 
			
		||||
  test('history event', async () => {
 | 
			
		||||
    let resolve;
 | 
			
		||||
    const promise = new Promise(r => resolve = r);
 | 
			
		||||
    plugin.on(EventType.HISTORY, throwErrFn);
 | 
			
		||||
    plugin.on(EventType.HISTORY, path => {
 | 
			
		||||
      assert.equal(path, '/path/to/awesomesauce');
 | 
			
		||||
      assert.isTrue(errorStub.calledOnce);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    element.handleEvent(EventType.HISTORY,
 | 
			
		||||
        {path: '/path/to/awesomesauce'});
 | 
			
		||||
    plugin.on(EventType.HISTORY, resolve);
 | 
			
		||||
    element.handleEvent(EventType.HISTORY, {path: '/path/to/awesomesauce'});
 | 
			
		||||
    const path = await promise;
 | 
			
		||||
    assert.equal(path, '/path/to/awesomesauce');
 | 
			
		||||
    assert.isTrue(errorStub.calledOnce);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('showchange event', done => {
 | 
			
		||||
  test('showchange event', async () => {
 | 
			
		||||
    let resolve;
 | 
			
		||||
    const promise = new Promise(r => resolve = r);
 | 
			
		||||
    const testChange = {
 | 
			
		||||
      _number: 42,
 | 
			
		||||
      revisions: {def: {_number: 2}, abc: {_number: 1}},
 | 
			
		||||
@@ -201,33 +203,39 @@ suite('gr-js-api-interface tests', () => {
 | 
			
		||||
    const expectedChange = {mergeable: false, ...testChange};
 | 
			
		||||
    plugin.on(EventType.SHOW_CHANGE, throwErrFn);
 | 
			
		||||
    plugin.on(EventType.SHOW_CHANGE, (change, revision, info) => {
 | 
			
		||||
      assert.deepEqual(change, expectedChange);
 | 
			
		||||
      assert.deepEqual(revision, testChange.revisions.abc);
 | 
			
		||||
      assert.deepEqual(info, {mergeable: false});
 | 
			
		||||
      assert.isTrue(errorStub.calledOnce);
 | 
			
		||||
      done();
 | 
			
		||||
      resolve({change, revision, info});
 | 
			
		||||
    });
 | 
			
		||||
    element.handleEvent(EventType.SHOW_CHANGE,
 | 
			
		||||
        {change: testChange, patchNum: 1, info: {mergeable: false}});
 | 
			
		||||
 | 
			
		||||
    const {change, revision, info} = await promise;
 | 
			
		||||
    assert.deepEqual(change, expectedChange);
 | 
			
		||||
    assert.deepEqual(revision, testChange.revisions.abc);
 | 
			
		||||
    assert.deepEqual(info, {mergeable: false});
 | 
			
		||||
    assert.isTrue(errorStub.calledOnce);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('show-revision-actions event', done => {
 | 
			
		||||
  test('show-revision-actions event', async () => {
 | 
			
		||||
    let resolve;
 | 
			
		||||
    const promise = new Promise(r => resolve = r);
 | 
			
		||||
    const testChange = {
 | 
			
		||||
      _number: 42,
 | 
			
		||||
      revisions: {def: {_number: 2}, abc: {_number: 1}},
 | 
			
		||||
    };
 | 
			
		||||
    plugin.on(EventType.SHOW_REVISION_ACTIONS, throwErrFn);
 | 
			
		||||
    plugin.on(EventType.SHOW_REVISION_ACTIONS, (actions, change) => {
 | 
			
		||||
      assert.deepEqual(change, testChange);
 | 
			
		||||
      assert.deepEqual(actions, {test: {}});
 | 
			
		||||
      assert.isTrue(errorStub.calledOnce);
 | 
			
		||||
      done();
 | 
			
		||||
      resolve({change, actions});
 | 
			
		||||
    });
 | 
			
		||||
    element.handleEvent(EventType.SHOW_REVISION_ACTIONS,
 | 
			
		||||
        {change: testChange, revisionActions: {test: {}}});
 | 
			
		||||
 | 
			
		||||
    const {change, actions} = await promise;
 | 
			
		||||
    assert.deepEqual(change, testChange);
 | 
			
		||||
    assert.deepEqual(actions, {test: {}});
 | 
			
		||||
    assert.isTrue(errorStub.calledOnce);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('handleEvent awaits plugins load', done => {
 | 
			
		||||
  test('handleEvent awaits plugins load', async () => {
 | 
			
		||||
    const testChange = {
 | 
			
		||||
      _number: 42,
 | 
			
		||||
      revisions: {def: {_number: 2}, abc: {_number: 1}},
 | 
			
		||||
@@ -242,21 +250,21 @@ suite('gr-js-api-interface tests', () => {
 | 
			
		||||
    // Timeout on loading plugins
 | 
			
		||||
    window.clock.tick(PLUGIN_LOADING_TIMEOUT_MS * 2);
 | 
			
		||||
 | 
			
		||||
    flush(() => {
 | 
			
		||||
      assert.isTrue(spy.called);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    await flush();
 | 
			
		||||
    assert.isTrue(spy.called);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('comment event', done => {
 | 
			
		||||
  test('comment event', async () => {
 | 
			
		||||
    let resolve;
 | 
			
		||||
    const promise = new Promise(r => resolve = r);
 | 
			
		||||
    const testCommentNode = {foo: 'bar'};
 | 
			
		||||
    plugin.on(EventType.COMMENT, throwErrFn);
 | 
			
		||||
    plugin.on(EventType.COMMENT, commentNode => {
 | 
			
		||||
      assert.deepEqual(commentNode, testCommentNode);
 | 
			
		||||
      assert.isTrue(errorStub.calledOnce);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    plugin.on(EventType.COMMENT, resolve);
 | 
			
		||||
    element.handleEvent(EventType.COMMENT, {node: testCommentNode});
 | 
			
		||||
 | 
			
		||||
    const commentNode = await promise;
 | 
			
		||||
    assert.deepEqual(commentNode, testCommentNode);
 | 
			
		||||
    assert.isTrue(errorStub.calledOnce);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('revert event', () => {
 | 
			
		||||
@@ -294,26 +302,32 @@ suite('gr-js-api-interface tests', () => {
 | 
			
		||||
    assert.isTrue(errorStub.calledOnce);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('commitmsgedit event', done => {
 | 
			
		||||
  test('commitmsgedit event', async () => {
 | 
			
		||||
    let resolve;
 | 
			
		||||
    const promise = new Promise(r => resolve = r);
 | 
			
		||||
    const testMsg = 'Test CL commit message';
 | 
			
		||||
    plugin.on(EventType.COMMIT_MSG_EDIT, throwErrFn);
 | 
			
		||||
    plugin.on(EventType.COMMIT_MSG_EDIT, (change, msg) => {
 | 
			
		||||
      assert.deepEqual(msg, testMsg);
 | 
			
		||||
      assert.isTrue(errorStub.calledOnce);
 | 
			
		||||
      done();
 | 
			
		||||
      resolve(msg);
 | 
			
		||||
    });
 | 
			
		||||
    element.handleCommitMessage(null, testMsg);
 | 
			
		||||
 | 
			
		||||
    const msg = await promise;
 | 
			
		||||
    assert.deepEqual(msg, testMsg);
 | 
			
		||||
    assert.isTrue(errorStub.calledOnce);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('labelchange event', done => {
 | 
			
		||||
  test('labelchange event', async () => {
 | 
			
		||||
    let resolve;
 | 
			
		||||
    const promise = new Promise(r => resolve = r);
 | 
			
		||||
    const testChange = {_number: 42};
 | 
			
		||||
    plugin.on(EventType.LABEL_CHANGE, throwErrFn);
 | 
			
		||||
    plugin.on(EventType.LABEL_CHANGE, change => {
 | 
			
		||||
      assert.deepEqual(change, testChange);
 | 
			
		||||
      assert.isTrue(errorStub.calledOnce);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    plugin.on(EventType.LABEL_CHANGE, resolve);
 | 
			
		||||
    element.handleEvent(EventType.LABEL_CHANGE, {change: testChange});
 | 
			
		||||
 | 
			
		||||
    const change = await promise;
 | 
			
		||||
    assert.deepEqual(change, testChange);
 | 
			
		||||
    assert.isTrue(errorStub.calledOnce);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('submitchange', () => {
 | 
			
		||||
@@ -327,24 +341,25 @@ suite('gr-js-api-interface tests', () => {
 | 
			
		||||
    assert.isTrue(errorStub.calledTwice);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('highlightjs-loaded event', done => {
 | 
			
		||||
  test('highlightjs-loaded event', async () => {
 | 
			
		||||
    let resolve;
 | 
			
		||||
    const promise = new Promise(r => resolve = r);
 | 
			
		||||
    const testHljs = {_number: 42};
 | 
			
		||||
    plugin.on(EventType.HIGHLIGHTJS_LOADED, throwErrFn);
 | 
			
		||||
    plugin.on(EventType.HIGHLIGHTJS_LOADED, hljs => {
 | 
			
		||||
      assert.deepEqual(hljs, testHljs);
 | 
			
		||||
      assert.isTrue(errorStub.calledOnce);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    plugin.on(EventType.HIGHLIGHTJS_LOADED, resolve);
 | 
			
		||||
    element.handleEvent(EventType.HIGHLIGHTJS_LOADED, {hljs: testHljs});
 | 
			
		||||
 | 
			
		||||
    const hljs = await promise;
 | 
			
		||||
    assert.deepEqual(hljs, testHljs);
 | 
			
		||||
    assert.isTrue(errorStub.calledOnce);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('getLoggedIn', done => {
 | 
			
		||||
  test('getLoggedIn', () => {
 | 
			
		||||
    // fake fetch for authCheck
 | 
			
		||||
    sinon.stub(window, 'fetch').callsFake(() => Promise.resolve({status: 204}));
 | 
			
		||||
    plugin.restApi().getLoggedIn()
 | 
			
		||||
    return plugin.restApi().getLoggedIn()
 | 
			
		||||
        .then(loggedIn => {
 | 
			
		||||
          assert.isTrue(loggedIn);
 | 
			
		||||
          done();
 | 
			
		||||
        });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -438,7 +438,7 @@ suite('gr-plugin-loader tests', () => {
 | 
			
		||||
    assert.isTrue(document.body.appendChild.calledTwice);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('can call awaitPluginsLoaded multiple times', done => {
 | 
			
		||||
  test('can call awaitPluginsLoaded multiple times', async () => {
 | 
			
		||||
    const plugins = [
 | 
			
		||||
      'http://e.com/foo/bar.js',
 | 
			
		||||
      'http://e.com/bar/foo.js',
 | 
			
		||||
@@ -456,13 +456,9 @@ suite('gr-plugin-loader tests', () => {
 | 
			
		||||
 | 
			
		||||
    pluginLoader.loadPlugins(plugins);
 | 
			
		||||
 | 
			
		||||
    pluginLoader.awaitPluginsLoaded().then(() => {
 | 
			
		||||
      assert.isTrue(installed);
 | 
			
		||||
 | 
			
		||||
      pluginLoader.awaitPluginsLoaded().then(() => {
 | 
			
		||||
        done();
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
    await pluginLoader.awaitPluginsLoaded();
 | 
			
		||||
    assert.isTrue(installed);
 | 
			
		||||
    await pluginLoader.awaitPluginsLoaded();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  suite('preloaded plugins', () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ suite('gr-lib-loader tests', () => {
 | 
			
		||||
    element._hljsState.callbacks = [];
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('only load once', done => {
 | 
			
		||||
  test('only load once', async () => {
 | 
			
		||||
    sinon.stub(element, '_getHLJSUrl').returns('');
 | 
			
		||||
    const firstCallHandler = sinon.stub();
 | 
			
		||||
    element.getHLJS().then(firstCallHandler);
 | 
			
		||||
@@ -67,13 +67,11 @@ suite('gr-lib-loader tests', () => {
 | 
			
		||||
 | 
			
		||||
    // Now load the library.
 | 
			
		||||
    resolveLoad();
 | 
			
		||||
    flush(() => {
 | 
			
		||||
      // The state should be loaded and both handlers called.
 | 
			
		||||
      assert.isFalse(element._hljsState.loading);
 | 
			
		||||
      assert.isTrue(firstCallHandler.called);
 | 
			
		||||
      assert.isTrue(secondCallHandler.called);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    await flush();
 | 
			
		||||
    // The state should be loaded and both handlers called.
 | 
			
		||||
    assert.isFalse(element._hljsState.loading);
 | 
			
		||||
    assert.isTrue(firstCallHandler.called);
 | 
			
		||||
    assert.isTrue(secondCallHandler.called);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  suite('preloaded', () => {
 | 
			
		||||
@@ -90,22 +88,17 @@ suite('gr-lib-loader tests', () => {
 | 
			
		||||
      delete window.hljs;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('returns hljs', done => {
 | 
			
		||||
    test('returns hljs', async () => {
 | 
			
		||||
      const firstCallHandler = sinon.stub();
 | 
			
		||||
      element.getHLJS().then(firstCallHandler);
 | 
			
		||||
      flush(() => {
 | 
			
		||||
        assert.isTrue(firstCallHandler.called);
 | 
			
		||||
        assert.isTrue(firstCallHandler.calledWith(hljsStub));
 | 
			
		||||
        done();
 | 
			
		||||
      });
 | 
			
		||||
      await flush();
 | 
			
		||||
      assert.isTrue(firstCallHandler.called);
 | 
			
		||||
      assert.isTrue(firstCallHandler.calledWith(hljsStub));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('configures hljs', done => {
 | 
			
		||||
      element.getHLJS().then(() => {
 | 
			
		||||
        assert.isTrue(window.hljs.configure.calledOnce);
 | 
			
		||||
        done();
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
    test('configures hljs', () => element.getHLJS().then(() => {
 | 
			
		||||
      assert.isTrue(window.hljs.configure.calledOnce);
 | 
			
		||||
    }));
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  suite('_getHLJSUrl', () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -59,13 +59,16 @@ suite('gr-list-view tests', () => {
 | 
			
		||||
        '/admin/projects/q/filter:plugins%252F,50');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('_onValueChange', done => {
 | 
			
		||||
  test('_onValueChange', async () => {
 | 
			
		||||
    let resolve;
 | 
			
		||||
    const promise = new Promise(r => resolve = r);
 | 
			
		||||
    element.path = '/admin/projects';
 | 
			
		||||
    sinon.stub(page, 'show').callsFake( url => {
 | 
			
		||||
      assert.equal(url, '/admin/projects/q/filter:test');
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    sinon.stub(page, 'show').callsFake(resolve);
 | 
			
		||||
 | 
			
		||||
    element.filter = 'test';
 | 
			
		||||
 | 
			
		||||
    const url = await promise;
 | 
			
		||||
    assert.equal(url, '/admin/projects/q/filter:test');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('_filterChanged not reload when swap between falsy values', () => {
 | 
			
		||||
@@ -76,23 +79,21 @@ suite('gr-list-view tests', () => {
 | 
			
		||||
    assert.isFalse(element._debounceReload.called);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('next button', done => {
 | 
			
		||||
  test('next button', () => {
 | 
			
		||||
    element.itemsPerPage = 25;
 | 
			
		||||
    let projects = new Array(26);
 | 
			
		||||
    flush();
 | 
			
		||||
 | 
			
		||||
    flush(() => {
 | 
			
		||||
      let loading;
 | 
			
		||||
      assert.isFalse(element._hideNextArrow(loading, projects));
 | 
			
		||||
      loading = true;
 | 
			
		||||
      assert.isTrue(element._hideNextArrow(loading, projects));
 | 
			
		||||
      loading = false;
 | 
			
		||||
      assert.isFalse(element._hideNextArrow(loading, projects));
 | 
			
		||||
      element._projects = [];
 | 
			
		||||
      assert.isTrue(element._hideNextArrow(loading, element._projects));
 | 
			
		||||
      projects = new Array(4);
 | 
			
		||||
      assert.isTrue(element._hideNextArrow(loading, projects));
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    let loading;
 | 
			
		||||
    assert.isFalse(element._hideNextArrow(loading, projects));
 | 
			
		||||
    loading = true;
 | 
			
		||||
    assert.isTrue(element._hideNextArrow(loading, projects));
 | 
			
		||||
    loading = false;
 | 
			
		||||
    assert.isFalse(element._hideNextArrow(loading, projects));
 | 
			
		||||
    element._projects = [];
 | 
			
		||||
    assert.isTrue(element._hideNextArrow(loading, element._projects));
 | 
			
		||||
    projects = new Array(4);
 | 
			
		||||
    assert.isTrue(element._hideNextArrow(loading, projects));
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('prev button', () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -47,42 +47,40 @@ suite('gr-overlay tests', () => {
 | 
			
		||||
        element._boundHandleClose);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('events are fired on fullscreen view', done => {
 | 
			
		||||
  test('events are fired on fullscreen view', async () => {
 | 
			
		||||
    sinon.stub(element, '_isMobile').returns(true);
 | 
			
		||||
    const openHandler = sinon.stub();
 | 
			
		||||
    const closeHandler = sinon.stub();
 | 
			
		||||
    element.addEventListener('fullscreen-overlay-opened', openHandler);
 | 
			
		||||
    element.addEventListener('fullscreen-overlay-closed', closeHandler);
 | 
			
		||||
 | 
			
		||||
    element.open().then(() => {
 | 
			
		||||
      assert.isTrue(element._isMobile.called);
 | 
			
		||||
      assert.isTrue(element._fullScreenOpen);
 | 
			
		||||
      assert.isTrue(openHandler.called);
 | 
			
		||||
    await element.open();
 | 
			
		||||
 | 
			
		||||
      element._overlayClosed();
 | 
			
		||||
      assert.isFalse(element._fullScreenOpen);
 | 
			
		||||
      assert.isTrue(closeHandler.called);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    assert.isTrue(element._isMobile.called);
 | 
			
		||||
    assert.isTrue(element._fullScreenOpen);
 | 
			
		||||
    assert.isTrue(openHandler.called);
 | 
			
		||||
 | 
			
		||||
    element._overlayClosed();
 | 
			
		||||
    assert.isFalse(element._fullScreenOpen);
 | 
			
		||||
    assert.isTrue(closeHandler.called);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('events are not fired on desktop view', done => {
 | 
			
		||||
  test('events are not fired on desktop view', async () => {
 | 
			
		||||
    sinon.stub(element, '_isMobile').returns(false);
 | 
			
		||||
    const openHandler = sinon.stub();
 | 
			
		||||
    const closeHandler = sinon.stub();
 | 
			
		||||
    element.addEventListener('fullscreen-overlay-opened', openHandler);
 | 
			
		||||
    element.addEventListener('fullscreen-overlay-closed', closeHandler);
 | 
			
		||||
 | 
			
		||||
    element.open().then(() => {
 | 
			
		||||
      assert.isTrue(element._isMobile.called);
 | 
			
		||||
      assert.isFalse(element._fullScreenOpen);
 | 
			
		||||
      assert.isFalse(openHandler.called);
 | 
			
		||||
    await element.open();
 | 
			
		||||
 | 
			
		||||
      element._overlayClosed();
 | 
			
		||||
      assert.isFalse(element._fullScreenOpen);
 | 
			
		||||
      assert.isFalse(closeHandler.called);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    assert.isTrue(element._isMobile.called);
 | 
			
		||||
    assert.isFalse(element._fullScreenOpen);
 | 
			
		||||
    assert.isFalse(openHandler.called);
 | 
			
		||||
 | 
			
		||||
    element._overlayClosed();
 | 
			
		||||
    assert.isFalse(element._fullScreenOpen);
 | 
			
		||||
    assert.isFalse(closeHandler.called);
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -108,19 +108,16 @@ suite('gr-repo-branch-picker tests', () => {
 | 
			
		||||
          });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('does not query when repo is unset', done => {
 | 
			
		||||
      element
 | 
			
		||||
          ._getRepoBranchesSuggestions('')
 | 
			
		||||
          .then(() => {
 | 
			
		||||
            assert.isFalse(element.$.restAPI.getRepoBranches.called);
 | 
			
		||||
            element.repo = 'gerrit';
 | 
			
		||||
            return element._getRepoBranchesSuggestions('');
 | 
			
		||||
          })
 | 
			
		||||
          .then(() => {
 | 
			
		||||
            assert.isTrue(element.$.restAPI.getRepoBranches.called);
 | 
			
		||||
            done();
 | 
			
		||||
          });
 | 
			
		||||
    });
 | 
			
		||||
    test('does not query when repo is unset', () => element
 | 
			
		||||
        ._getRepoBranchesSuggestions('')
 | 
			
		||||
        .then(() => {
 | 
			
		||||
          assert.isFalse(element.$.restAPI.getRepoBranches.called);
 | 
			
		||||
          element.repo = 'gerrit';
 | 
			
		||||
          return element._getRepoBranchesSuggestions('');
 | 
			
		||||
        })
 | 
			
		||||
        .then(() => {
 | 
			
		||||
          assert.isTrue(element.$.restAPI.getRepoBranches.called);
 | 
			
		||||
        }));
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -54,7 +54,7 @@ suite('gr-rest-api-interface tests', () => {
 | 
			
		||||
    window.CANONICAL_PATH = originalCanonicalPath;
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('parent diff comments are properly grouped', done => {
 | 
			
		||||
  test('parent diff comments are properly grouped', () => {
 | 
			
		||||
    sinon.stub(element._restApiHelper, 'fetchJSON')
 | 
			
		||||
        .callsFake(() => Promise.resolve({
 | 
			
		||||
          '/COMMIT_MSG': [],
 | 
			
		||||
@@ -70,7 +70,7 @@ suite('gr-rest-api-interface tests', () => {
 | 
			
		||||
            },
 | 
			
		||||
          ],
 | 
			
		||||
        }));
 | 
			
		||||
    element._getDiffComments('42', '', 'PARENT', 1, 'sieve.go').then(
 | 
			
		||||
    return element._getDiffComments('42', '', 'PARENT', 1, 'sieve.go').then(
 | 
			
		||||
        obj => {
 | 
			
		||||
          assert.equal(obj.baseComments.length, 1);
 | 
			
		||||
          assert.deepEqual(obj.baseComments[0], {
 | 
			
		||||
@@ -85,7 +85,6 @@ suite('gr-rest-api-interface tests', () => {
 | 
			
		||||
            path: 'sieve.go',
 | 
			
		||||
            updated: '2017-02-03 22:32:28.000000000',
 | 
			
		||||
          });
 | 
			
		||||
          done();
 | 
			
		||||
        });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@@ -194,10 +193,10 @@ suite('gr-rest-api-interface tests', () => {
 | 
			
		||||
    assert.deepEqual(element._setRanges(comments), expectedResult);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('differing patch diff comments are properly grouped', done => {
 | 
			
		||||
  test('differing patch diff comments are properly grouped', () => {
 | 
			
		||||
    sinon.stub(element, 'getFromProjectLookup')
 | 
			
		||||
        .returns(Promise.resolve('test'));
 | 
			
		||||
    sinon.stub(element._restApiHelper, 'fetchJSON').callsFake( request => {
 | 
			
		||||
    sinon.stub(element._restApiHelper, 'fetchJSON').callsFake(request => {
 | 
			
		||||
      const url = request.url;
 | 
			
		||||
      if (url === '/changes/test~42/revisions/1') {
 | 
			
		||||
        return Promise.resolve({
 | 
			
		||||
@@ -235,7 +234,7 @@ suite('gr-rest-api-interface tests', () => {
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    element._getDiffComments('42', '', 1, 2, 'sieve.go').then(
 | 
			
		||||
    return element._getDiffComments('42', '', 1, 2, 'sieve.go').then(
 | 
			
		||||
        obj => {
 | 
			
		||||
          assert.equal(obj.baseComments.length, 1);
 | 
			
		||||
          assert.deepEqual(obj.baseComments[0], {
 | 
			
		||||
@@ -254,26 +253,26 @@ suite('gr-rest-api-interface tests', () => {
 | 
			
		||||
            path: 'sieve.go',
 | 
			
		||||
            updated: '2017-02-04 22:33:28.000000000',
 | 
			
		||||
          });
 | 
			
		||||
          done();
 | 
			
		||||
        });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('server error', done => {
 | 
			
		||||
  test('server error', () => {
 | 
			
		||||
    const getResponseObjectStub = sinon.stub(element, 'getResponseObject');
 | 
			
		||||
    window.fetch.returns(Promise.resolve({ok: false}));
 | 
			
		||||
    const serverErrorEventPromise = new Promise(resolve => {
 | 
			
		||||
      element.addEventListener('server-error', resolve);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    element._restApiHelper.fetchJSON({}).then(response => {
 | 
			
		||||
    return Promise.all([element._restApiHelper.fetchJSON({}).then(response => {
 | 
			
		||||
      assert.isUndefined(response);
 | 
			
		||||
      assert.isTrue(getResponseObjectStub.notCalled);
 | 
			
		||||
      serverErrorEventPromise.then(() => done());
 | 
			
		||||
    });
 | 
			
		||||
    }), serverErrorEventPromise]);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('legacy n,z key in change url is replaced', async () => {
 | 
			
		||||
    sinon.stub(element, 'getConfig').callsFake( async () => { return {}; });
 | 
			
		||||
    sinon.stub(element, 'getConfig').callsFake(async () => {
 | 
			
		||||
      return {};
 | 
			
		||||
    });
 | 
			
		||||
    const stub = sinon.stub(element._restApiHelper, 'fetchJSON')
 | 
			
		||||
        .returns(Promise.resolve([]));
 | 
			
		||||
    await element.getChanges(1, null, 'n,z');
 | 
			
		||||
@@ -289,49 +288,42 @@ suite('gr-rest-api-interface tests', () => {
 | 
			
		||||
    assert.isFalse(element._restApiHelper._cache.has(cacheKey));
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('getAccount when resp is null does not add anything to the cache',
 | 
			
		||||
      done => {
 | 
			
		||||
        const cacheKey = '/accounts/self/detail';
 | 
			
		||||
        const stub = sinon.stub(element._restApiHelper, 'fetchCacheURL')
 | 
			
		||||
            .callsFake(() => Promise.resolve());
 | 
			
		||||
  test('getAccount when resp is null does not add to cache', async () => {
 | 
			
		||||
    const cacheKey = '/accounts/self/detail';
 | 
			
		||||
    const stub = sinon.stub(element._restApiHelper, 'fetchCacheURL')
 | 
			
		||||
        .callsFake(() => Promise.resolve());
 | 
			
		||||
 | 
			
		||||
        element.getAccount().then(() => {
 | 
			
		||||
          assert.isTrue(stub.called);
 | 
			
		||||
          assert.isFalse(element._restApiHelper._cache.has(cacheKey));
 | 
			
		||||
          done();
 | 
			
		||||
        });
 | 
			
		||||
    await element.getAccount();
 | 
			
		||||
    assert.isTrue(stub.called);
 | 
			
		||||
    assert.isFalse(element._restApiHelper._cache.has(cacheKey));
 | 
			
		||||
 | 
			
		||||
        element._restApiHelper._cache.set(cacheKey, 'fake cache');
 | 
			
		||||
        stub.lastCall.args[0].errFn();
 | 
			
		||||
      });
 | 
			
		||||
    element._restApiHelper._cache.set(cacheKey, 'fake cache');
 | 
			
		||||
    stub.lastCall.args[0].errFn();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('getAccount does not add to the cache when resp.status is 403',
 | 
			
		||||
      done => {
 | 
			
		||||
        const cacheKey = '/accounts/self/detail';
 | 
			
		||||
        const stub = sinon.stub(element._restApiHelper, 'fetchCacheURL')
 | 
			
		||||
            .callsFake(() => Promise.resolve());
 | 
			
		||||
  test('getAccount does not add to cache when status is 403', async () => {
 | 
			
		||||
    const cacheKey = '/accounts/self/detail';
 | 
			
		||||
    const stub = sinon.stub(element._restApiHelper, 'fetchCacheURL')
 | 
			
		||||
        .callsFake(() => Promise.resolve());
 | 
			
		||||
 | 
			
		||||
        element.getAccount().then(() => {
 | 
			
		||||
          assert.isTrue(stub.called);
 | 
			
		||||
          assert.isFalse(element._restApiHelper._cache.has(cacheKey));
 | 
			
		||||
          done();
 | 
			
		||||
        });
 | 
			
		||||
        element._cache.set(cacheKey, 'fake cache');
 | 
			
		||||
        stub.lastCall.args[0].errFn({status: 403});
 | 
			
		||||
      });
 | 
			
		||||
    await element.getAccount();
 | 
			
		||||
    assert.isTrue(stub.called);
 | 
			
		||||
    assert.isFalse(element._restApiHelper._cache.has(cacheKey));
 | 
			
		||||
 | 
			
		||||
  test('getAccount when resp is successful', done => {
 | 
			
		||||
    element._cache.set(cacheKey, 'fake cache');
 | 
			
		||||
    stub.lastCall.args[0].errFn({status: 403});
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('getAccount when resp is successful', async () => {
 | 
			
		||||
    const cacheKey = '/accounts/self/detail';
 | 
			
		||||
    const stub = sinon.stub(element._restApiHelper, 'fetchCacheURL').callsFake(
 | 
			
		||||
        () => Promise.resolve());
 | 
			
		||||
 | 
			
		||||
    element.getAccount().then(response => {
 | 
			
		||||
      assert.isTrue(stub.called);
 | 
			
		||||
      assert.equal(element._restApiHelper._cache.get(cacheKey), 'fake cache');
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    element._restApiHelper._cache.set(cacheKey, 'fake cache');
 | 
			
		||||
    await element.getAccount();
 | 
			
		||||
 | 
			
		||||
    element._restApiHelper._cache.set(cacheKey, 'fake cache');
 | 
			
		||||
    assert.isTrue(stub.called);
 | 
			
		||||
    assert.equal(element._restApiHelper._cache.get(cacheKey), 'fake cache');
 | 
			
		||||
    stub.lastCall.args[0].errFn({});
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@@ -346,61 +338,57 @@ suite('gr-rest-api-interface tests', () => {
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  test('getPreferences returns correctly on small screens logged in',
 | 
			
		||||
      done => {
 | 
			
		||||
      () => {
 | 
			
		||||
        const testJSON = {diff_view: 'SIDE_BY_SIDE'};
 | 
			
		||||
        const loggedIn = true;
 | 
			
		||||
        const smallScreen = true;
 | 
			
		||||
 | 
			
		||||
        preferenceSetup(testJSON, loggedIn, smallScreen);
 | 
			
		||||
 | 
			
		||||
        element.getPreferences().then(obj => {
 | 
			
		||||
        return element.getPreferences().then(obj => {
 | 
			
		||||
          assert.equal(obj.default_diff_view, 'UNIFIED_DIFF');
 | 
			
		||||
          assert.equal(obj.diff_view, 'SIDE_BY_SIDE');
 | 
			
		||||
          done();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
  test('getPreferences returns correctly on small screens not logged in',
 | 
			
		||||
      done => {
 | 
			
		||||
      () => {
 | 
			
		||||
        const testJSON = {diff_view: 'SIDE_BY_SIDE'};
 | 
			
		||||
        const loggedIn = false;
 | 
			
		||||
        const smallScreen = true;
 | 
			
		||||
 | 
			
		||||
        preferenceSetup(testJSON, loggedIn, smallScreen);
 | 
			
		||||
        element.getPreferences().then(obj => {
 | 
			
		||||
        return element.getPreferences().then(obj => {
 | 
			
		||||
          assert.equal(obj.default_diff_view, 'UNIFIED_DIFF');
 | 
			
		||||
          assert.equal(obj.diff_view, 'SIDE_BY_SIDE');
 | 
			
		||||
          done();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
  test('getPreferences returns correctly on larger screens logged in',
 | 
			
		||||
      done => {
 | 
			
		||||
      () => {
 | 
			
		||||
        const testJSON = {diff_view: 'UNIFIED_DIFF'};
 | 
			
		||||
        const loggedIn = true;
 | 
			
		||||
        const smallScreen = false;
 | 
			
		||||
 | 
			
		||||
        preferenceSetup(testJSON, loggedIn, smallScreen);
 | 
			
		||||
 | 
			
		||||
        element.getPreferences().then(obj => {
 | 
			
		||||
        return element.getPreferences().then(obj => {
 | 
			
		||||
          assert.equal(obj.default_diff_view, 'UNIFIED_DIFF');
 | 
			
		||||
          assert.equal(obj.diff_view, 'UNIFIED_DIFF');
 | 
			
		||||
          done();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
  test('getPreferences returns correctly on larger screens not logged in',
 | 
			
		||||
      done => {
 | 
			
		||||
      () => {
 | 
			
		||||
        const testJSON = {diff_view: 'UNIFIED_DIFF'};
 | 
			
		||||
        const loggedIn = false;
 | 
			
		||||
        const smallScreen = false;
 | 
			
		||||
 | 
			
		||||
        preferenceSetup(testJSON, loggedIn, smallScreen);
 | 
			
		||||
 | 
			
		||||
        element.getPreferences().then(obj => {
 | 
			
		||||
        return element.getPreferences().then(obj => {
 | 
			
		||||
          assert.equal(obj.default_diff_view, 'SIDE_BY_SIDE');
 | 
			
		||||
          assert.equal(obj.diff_view, 'SIDE_BY_SIDE');
 | 
			
		||||
          done();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
@@ -411,10 +399,10 @@ suite('gr-rest-api-interface tests', () => {
 | 
			
		||||
    assert.equal(sendStub.lastCall.args[0].body.download_scheme, 'http');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('getDiffPreferences returns correct defaults', done => {
 | 
			
		||||
  test('getDiffPreferences returns correct defaults', () => {
 | 
			
		||||
    sinon.stub(element, 'getLoggedIn').callsFake(() => Promise.resolve(false));
 | 
			
		||||
 | 
			
		||||
    element.getDiffPreferences().then(obj => {
 | 
			
		||||
    return element.getDiffPreferences().then(obj => {
 | 
			
		||||
      assert.equal(obj.auto_hide_diff_table_header, true);
 | 
			
		||||
      assert.equal(obj.context, 10);
 | 
			
		||||
      assert.equal(obj.cursor_blink_rate, 0);
 | 
			
		||||
@@ -429,7 +417,6 @@ suite('gr-rest-api-interface tests', () => {
 | 
			
		||||
      assert.equal(obj.syntax_highlighting, true);
 | 
			
		||||
      assert.equal(obj.tab_size, 8);
 | 
			
		||||
      assert.equal(obj.theme, 'DEFAULT');
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@@ -440,10 +427,10 @@ suite('gr-rest-api-interface tests', () => {
 | 
			
		||||
    assert.equal(sendStub.lastCall.args[0].body.show_tabs, false);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('getEditPreferences returns correct defaults', done => {
 | 
			
		||||
  test('getEditPreferences returns correct defaults', () => {
 | 
			
		||||
    sinon.stub(element, 'getLoggedIn').callsFake(() => Promise.resolve(false));
 | 
			
		||||
 | 
			
		||||
    element.getEditPreferences().then(obj => {
 | 
			
		||||
    return element.getEditPreferences().then(obj => {
 | 
			
		||||
      assert.equal(obj.auto_close_brackets, false);
 | 
			
		||||
      assert.equal(obj.cursor_blink_rate, 0);
 | 
			
		||||
      assert.equal(obj.hide_line_numbers, false);
 | 
			
		||||
@@ -460,7 +447,6 @@ suite('gr-rest-api-interface tests', () => {
 | 
			
		||||
      assert.equal(obj.syntax_highlighting, true);
 | 
			
		||||
      assert.equal(obj.tab_size, 8);
 | 
			
		||||
      assert.equal(obj.theme, 'DEFAULT');
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@@ -492,9 +478,9 @@ suite('gr-rest-api-interface tests', () => {
 | 
			
		||||
          '/accounts/self/status');
 | 
			
		||||
      assert.deepEqual(sendStub.lastCall.args[0].body,
 | 
			
		||||
          {status: 'OOO'});
 | 
			
		||||
      assert.deepEqual(element._restApiHelper
 | 
			
		||||
          ._cache.get('/accounts/self/detail'),
 | 
			
		||||
      {status: 'OOO'});
 | 
			
		||||
      assert.deepEqual(
 | 
			
		||||
          element._restApiHelper._cache.get('/accounts/self/detail'),
 | 
			
		||||
          {status: 'OOO'});
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@@ -513,7 +499,9 @@ suite('gr-rest-api-interface tests', () => {
 | 
			
		||||
      assert.equal(obj.sendDiffDraft.length, 2);
 | 
			
		||||
      assert.isTrue(!!element.hasPendingDiffDrafts());
 | 
			
		||||
 | 
			
		||||
      for (const promise of obj.sendDiffDraft) { promise.resolve(); }
 | 
			
		||||
      for (const promise of obj.sendDiffDraft) {
 | 
			
		||||
        promise.resolve();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return element.awaitPendingDiffDrafts().then(() => {
 | 
			
		||||
        assert.equal(obj.sendDiffDraft.length, 0);
 | 
			
		||||
@@ -544,41 +532,36 @@ suite('gr-rest-api-interface tests', () => {
 | 
			
		||||
            });
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      test('_failForCreate200 fails on 200', done => {
 | 
			
		||||
      test('_failForCreate200 fails on 200', () => {
 | 
			
		||||
        const result = {
 | 
			
		||||
          ok: true,
 | 
			
		||||
          status: 200,
 | 
			
		||||
          headers: {entries: () => [
 | 
			
		||||
            ['Set-CoOkiE', 'secret'],
 | 
			
		||||
            ['Innocuous', 'hello'],
 | 
			
		||||
          ]},
 | 
			
		||||
          headers: {
 | 
			
		||||
            entries: () => [
 | 
			
		||||
              ['Set-CoOkiE', 'secret'],
 | 
			
		||||
              ['Innocuous', 'hello'],
 | 
			
		||||
            ],
 | 
			
		||||
          },
 | 
			
		||||
        };
 | 
			
		||||
        element._failForCreate200(Promise.resolve(result))
 | 
			
		||||
        return element._failForCreate200(Promise.resolve(result))
 | 
			
		||||
            .then(() => {
 | 
			
		||||
              assert.isTrue(false, 'Promise should not resolve');
 | 
			
		||||
              assert.fail('Error expected.');
 | 
			
		||||
            })
 | 
			
		||||
            .catch(e => {
 | 
			
		||||
              assert.isOk(e);
 | 
			
		||||
              assert.include(e.message, 'Saving draft resulted in HTTP 200');
 | 
			
		||||
              assert.include(e.message, 'hello');
 | 
			
		||||
              assert.notInclude(e.message, 'secret');
 | 
			
		||||
              done();
 | 
			
		||||
            });
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      test('_failForCreate200 does not fail on 201', done => {
 | 
			
		||||
      test('_failForCreate200 does not fail on 201', () => {
 | 
			
		||||
        const result = {
 | 
			
		||||
          ok: true,
 | 
			
		||||
          status: 201,
 | 
			
		||||
          headers: {entries: () => []},
 | 
			
		||||
        };
 | 
			
		||||
        element._failForCreate200(Promise.resolve(result))
 | 
			
		||||
            .then(() => {
 | 
			
		||||
              done();
 | 
			
		||||
            })
 | 
			
		||||
            .catch(e => {
 | 
			
		||||
              assert.isTrue(false, 'Promise should not fail');
 | 
			
		||||
            });
 | 
			
		||||
        return element._failForCreate200(Promise.resolve(result));
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
@@ -900,11 +883,15 @@ suite('gr-rest-api-interface tests', () => {
 | 
			
		||||
    suite('change detail options', () => {
 | 
			
		||||
      setup(() => {
 | 
			
		||||
        sinon.stub(element, '_getChangeDetail').callsFake(
 | 
			
		||||
            async (changeNum, options) => { return {changeNum, options}; });
 | 
			
		||||
            async (changeNum, options) => {
 | 
			
		||||
              return {changeNum, options};
 | 
			
		||||
            });
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      test('signed pushes disabled', async () => {
 | 
			
		||||
        sinon.stub(element, 'getConfig').callsFake( async () => { return {}; });
 | 
			
		||||
        sinon.stub(element, 'getConfig').callsFake(async () => {
 | 
			
		||||
          return {};
 | 
			
		||||
        });
 | 
			
		||||
        const {changeNum, options} = await element.getChangeDetail(123);
 | 
			
		||||
        assert.strictEqual(123, changeNum);
 | 
			
		||||
        assert.isNotOk(
 | 
			
		||||
@@ -912,7 +899,7 @@ suite('gr-rest-api-interface tests', () => {
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      test('signed pushes enabled', async () => {
 | 
			
		||||
        sinon.stub(element, 'getConfig').callsFake( async () => {
 | 
			
		||||
        sinon.stub(element, 'getConfig').callsFake(async () => {
 | 
			
		||||
          return {receive: {enable_signed_push: true}};
 | 
			
		||||
        });
 | 
			
		||||
        const {changeNum, options} = await element.getChangeDetail(123);
 | 
			
		||||
@@ -1289,21 +1276,24 @@ suite('gr-rest-api-interface tests', () => {
 | 
			
		||||
    return Promise.all([edit, normal]);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('getFileContent suppresses 404s', done => {
 | 
			
		||||
  test('getFileContent suppresses 404s', () => {
 | 
			
		||||
    const res = {status: 404};
 | 
			
		||||
    const handler = e => {
 | 
			
		||||
      assert.isFalse(e.detail.res.status === 404);
 | 
			
		||||
      done();
 | 
			
		||||
    };
 | 
			
		||||
    element.addEventListener('server-error', handler);
 | 
			
		||||
    const spy = sinon.spy();
 | 
			
		||||
    element.addEventListener('server-error', spy);
 | 
			
		||||
    sinon.stub(appContext.authService, 'fetch').returns(Promise.resolve(res));
 | 
			
		||||
    sinon.stub(element, '_changeBaseURL').returns(Promise.resolve(''));
 | 
			
		||||
    element.getFileContent('1', 'tst/path', '1').then(() => {
 | 
			
		||||
      flush();
 | 
			
		||||
    return element.getFileContent('1', 'tst/path', '1')
 | 
			
		||||
        .then(() => {
 | 
			
		||||
          flush();
 | 
			
		||||
          assert.isFalse(spy.called);
 | 
			
		||||
 | 
			
		||||
      res.status = 500;
 | 
			
		||||
      element.getFileContent('1', 'tst/path', '1');
 | 
			
		||||
    });
 | 
			
		||||
          res.status = 500;
 | 
			
		||||
          return element.getFileContent('1', 'tst/path', '1');
 | 
			
		||||
        })
 | 
			
		||||
        .then(() => {
 | 
			
		||||
          assert.isTrue(spy.called);
 | 
			
		||||
          assert.notEqual(spy.lastCall.args[0].detail.res.status, 404);
 | 
			
		||||
        });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('getChangeFilesOrEditFiles is edit-sensitive', () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -77,14 +77,13 @@ suite('gr-rest-api-helper tests', () => {
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('JSON prefix is properly removed', done => {
 | 
			
		||||
    helper.fetchJSON({url: '/dummy/url'}).then(obj => {
 | 
			
		||||
      assert.deepEqual(obj, {hello: 'bonjour'});
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
  test('JSON prefix is properly removed',
 | 
			
		||||
      () => helper.fetchJSON({url: '/dummy/url'}).then(obj => {
 | 
			
		||||
        assert.deepEqual(obj, {hello: 'bonjour'});
 | 
			
		||||
      })
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  test('cached results', done => {
 | 
			
		||||
  test('cached results', () => {
 | 
			
		||||
    let n = 0;
 | 
			
		||||
    sinon.stub(helper, 'fetchJSON').callsFake(() => Promise.resolve(++n));
 | 
			
		||||
    const promises = [];
 | 
			
		||||
@@ -92,21 +91,19 @@ suite('gr-rest-api-helper tests', () => {
 | 
			
		||||
    promises.push(helper.fetchCacheURL('/foo'));
 | 
			
		||||
    promises.push(helper.fetchCacheURL('/foo'));
 | 
			
		||||
 | 
			
		||||
    Promise.all(promises).then(results => {
 | 
			
		||||
    return Promise.all(promises).then(results => {
 | 
			
		||||
      assert.deepEqual(results, [1, 1, 1]);
 | 
			
		||||
      helper.fetchCacheURL('/foo').then(foo => {
 | 
			
		||||
      return helper.fetchCacheURL('/foo').then(foo => {
 | 
			
		||||
        assert.equal(foo, 1);
 | 
			
		||||
        done();
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('cached promise', done => {
 | 
			
		||||
  test('cached promise', () => {
 | 
			
		||||
    const promise = Promise.reject(new Error('foo'));
 | 
			
		||||
    cache.set('/foo', promise);
 | 
			
		||||
    helper.fetchCacheURL({url: '/foo'}).catch(p => {
 | 
			
		||||
    return helper.fetchCacheURL({url: '/foo'}).catch(p => {
 | 
			
		||||
      assert.equal(p.message, 'foo');
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@@ -144,7 +141,7 @@ suite('gr-rest-api-helper tests', () => {
 | 
			
		||||
    assert.equal(url, window.CANONICAL_PATH + '/path/?l=c&l=b&l=a');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('request callbacks can be canceled', done => {
 | 
			
		||||
  test('request callbacks can be canceled', () => {
 | 
			
		||||
    let cancelCalled = false;
 | 
			
		||||
    window.fetch.returns(Promise.resolve({
 | 
			
		||||
      body: {
 | 
			
		||||
@@ -152,12 +149,10 @@ suite('gr-rest-api-helper tests', () => {
 | 
			
		||||
      },
 | 
			
		||||
    }));
 | 
			
		||||
    const cancelCondition = () => true;
 | 
			
		||||
    helper.fetchJSON({url: '/dummy/url', cancelCondition}).then(
 | 
			
		||||
        obj => {
 | 
			
		||||
          assert.isUndefined(obj);
 | 
			
		||||
          assert.isTrue(cancelCalled);
 | 
			
		||||
          done();
 | 
			
		||||
        });
 | 
			
		||||
    return helper.fetchJSON({url: '/dummy/url', cancelCondition}).then(obj => {
 | 
			
		||||
      assert.isUndefined(obj);
 | 
			
		||||
      assert.isTrue(cancelCalled);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user