<!DOCTYPE html>
<!--
@license
Copyright (C) 2016 The Android Open Source Project

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>gr-change-actions-js-api</title>

<script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
<script src="../../../bower_components/web-component-tester/browser.js"></script>
<link rel="import" href="../../../test/common-test-setup.html"/>
<!--
This must refer to the element this interface is wrapping around. Otherwise
breaking changes to gr-change-actions won’t be noticed.
-->
<link rel="import" href="../../change/gr-change-actions/gr-change-actions.html">

<script>void(0);</script>

<test-fixture id="basic">
  <template>
    <gr-change-actions></gr-change-actions>
  </template>
</test-fixture>

<script>
  suite('gr-js-api-interface tests', () => {
    let element;
    let changeActions;
    let plugin;

    // Because deepEqual doesn’t behave in Safari.
    function assertArraysEqual(actual, expected) {
      assert.equal(actual.length, expected.length);
      for (let i = 0; i < actual.length; i++) {
        assert.equal(actual[i], expected[i]);
      }
    }

    suite('early init', () => {
      setup(() => {
        Gerrit._resetPlugins();
        Gerrit.install(p => { plugin = p; }, '0.1',
            'http://test.com/plugins/testplugin/static/test.js');
        // Mimic all plugins loaded.
        Gerrit._setPluginsPending([]);
        changeActions = plugin.changeActions();
        element = fixture('basic');
      });

      teardown(() => {
        changeActions = null;
      });

      test('does not throw', ()=> {
        assert.doesNotThrow(() => {
          changeActions.add('change', 'foo');
        });
      });
    });

    suite('normal init', () => {
      setup(() => {
        Gerrit._resetPlugins();
        element = fixture('basic');
        sinon.stub(element, '_editStatusChanged');
        element.change = {};
        element._hasKnownChainState = false;
        Gerrit.install(p => { plugin = p; }, '0.1',
            'http://test.com/plugins/testplugin/static/test.js');
        changeActions = plugin.changeActions();
        // Mimic all plugins loaded.
        Gerrit._setPluginsPending([]);
      });

      teardown(() => {
        changeActions = null;
      });

      test('property existence', () => {
        const properties = [
          'ActionType',
          'ChangeActions',
          'RevisionActions',
        ];
        for (const p of properties) {
          assertArraysEqual(changeActions[p], element[p]);
        }
      });

      test('add/remove primary action keys', () => {
        element.primaryActionKeys = [];
        changeActions.addPrimaryActionKey('foo');
        assertArraysEqual(element.primaryActionKeys, ['foo']);
        changeActions.addPrimaryActionKey('foo');
        assertArraysEqual(element.primaryActionKeys, ['foo']);
        changeActions.addPrimaryActionKey('bar');
        assertArraysEqual(element.primaryActionKeys, ['foo', 'bar']);
        changeActions.removePrimaryActionKey('foo');
        assertArraysEqual(element.primaryActionKeys, ['bar']);
        changeActions.removePrimaryActionKey('baz');
        assertArraysEqual(element.primaryActionKeys, ['bar']);
        changeActions.removePrimaryActionKey('bar');
        assertArraysEqual(element.primaryActionKeys, []);
      });

      test('action buttons', done => {
        const key = changeActions.add(changeActions.ActionType.REVISION, 'Bork!');
        const handler = sinon.spy();
        changeActions.addTapListener(key, handler);
        flush(() => {
          MockInteractions.tap(element.$$('[data-action-key="' + key + '"]'));
          assert(handler.calledOnce);
          changeActions.removeTapListener(key, handler);
          MockInteractions.tap(element.$$('[data-action-key="' + key + '"]'));
          assert(handler.calledOnce);
          changeActions.remove(key);
          flush(() => {
            assert.isNull(element.$$('[data-action-key="' + key + '"]'));
            done();
          });
        });
      });

      test('action button properties', done => {
        const key = changeActions.add(changeActions.ActionType.REVISION, 'Bork!');
        flush(() => {
          const button = element.$$('[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(Polymer.dom(button).querySelector('iron-icon').icon,
                'gr-icons:pupper');
            done();
          });
        });
      });

      test('hide action buttons', done => {
        const key = changeActions.add(changeActions.ActionType.REVISION, 'Bork!');
        flush(() => {
          const button = element.$$('[data-action-key="' + key + '"]');
          assert.isOk(button);
          assert.isFalse(button.hasAttribute('hidden'));
          changeActions.setActionHidden(
              changeActions.ActionType.REVISION, key, true);
          flush(() => {
            const button = element.$$('[data-action-key="' + key + '"]');
            assert.isNotOk(button);
            done();
          });
        });
      });

      test('move action button to overflow', done => {
        const key = changeActions.add(changeActions.ActionType.REVISION, 'Bork!');
        flush(() => {
          assert.isTrue(element.$.moreActions.hidden);
          assert.isOk(element.$$('[data-action-key="' + key + '"]'));
          changeActions.setActionOverflow(
              changeActions.ActionType.REVISION, key, true);
          flush(() => {
            assert.isNotOk(element.$$('[data-action-key="' + key + '"]'));
            assert.isFalse(element.$.moreActions.hidden);
            assert.strictEqual(element.$.moreActions.items[0].name, 'Bork!');
            done();
          });
        });
      });

      test('change actions priority', done => {
        const key1 =
          changeActions.add(changeActions.ActionType.REVISION, 'Bork!');
        const key2 =
          changeActions.add(changeActions.ActionType.CHANGE, 'Squanch?');
        flush(() => {
          let buttons =
            Polymer.dom(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 =
              Polymer.dom(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();
          });
        });
      });
    });
  });
</script>
