<!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-annotation-actions-js-api-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"/>
<link rel="import" href="../../change/gr-change-actions/gr-change-actions.html">

<test-fixture id="basic">
  <template>
    <span hidden id="annotation-span">
      <label for="annotation-checkbox" id="annotation-label"></label>
      <input is="iron-input" type="checkbox" id="annotation-checkbox" disabled>
    </span>
  </template>
</test-fixture>

<script>
  suite('gr-annotation-actions-js-api tests', () => {
    let annotationActions;
    let sandbox;
    let plugin;

    setup(() => {
      sandbox = sinon.sandbox.create();
      Gerrit.install(p => { plugin = p; }, '0.1',
          'http://test.com/plugins/testplugin/static/test.js');
      annotationActions = plugin.annotationApi();
    });

    teardown(() => {
      annotationActions = null;
      sandbox.restore();
    });

    test('add/get layer', () => {
      const str = 'lorem ipsum blah blah';
      const line = {text: str};
      el = document.createElement('div');
      el.textContent = str;
      const changeNum = 1234;
      const patchNum = 2;
      let testLayerFuncCalled = false;

      const testLayerFunc = context => {
        testLayerFuncCalled = true;
        assert.equal(context.line, line);
        assert.equal(context.changeNum, changeNum);
        assert.equal(context.patchNum, 2);
      };
      annotationActions.addLayer(testLayerFunc);

      const annotationLayer = annotationActions.getLayer(
          '/dummy/path', changeNum, patchNum);

      annotationLayer.annotate(el, line);
      assert.isTrue(testLayerFuncCalled);
    });

    test('add notifier', () => {
      const path1 = '/dummy/path1';
      const path2 = '/dummy/path2';
      const annotationLayer1 = annotationActions.getLayer(path1, 1, 2);
      const annotationLayer2 = annotationActions.getLayer(path2, 1, 2);
      const layer1Spy = sandbox.spy(annotationLayer1, 'notifyListeners');
      const layer2Spy = sandbox.spy(annotationLayer2, 'notifyListeners');

      let notify;
      const notifyFunc = n => {
        notifyFuncCalled = true;
        notify = n;
      };
      annotationActions.addNotifier(notifyFunc);
      assert.isTrue(notifyFuncCalled);

      // Assert that no layers are invoked with a different path.
      notify('/dummy/path3', 0, 10, 'right');
      assert.isFalse(layer1Spy.called);
      assert.isFalse(layer2Spy.called);

      // Assert that only the 1st layer is invoked with path1.
      notify(path1, 0, 10, 'right');
      assert.isTrue(layer1Spy.called);
      assert.isFalse(layer2Spy.called);

      // Reset spies.
      layer1Spy.reset();
      layer2Spy.reset();

      // Assert that only the 2nd layer is invoked with path2.
      notify(path2, 0, 20, 'left');
      assert.isFalse(layer1Spy.called);
      assert.isTrue(layer2Spy.called);
    });

    test('toggle checkbox', () => {
      fakeEl = {content: fixture('basic')};
      const hookStub = {onAttached: sandbox.stub()};
      sandbox.stub(plugin, 'hook').returns(hookStub);

      let checkbox;
      let onAttachedFuncCalled = false;
      const onAttachedFunc = c => {
        checkbox = c;
        onAttachedFuncCalled = true;
      };
      annotationActions.enableToggleCheckbox('test label', onAttachedFunc);
      emulateAttached = () => hookStub.onAttached.callArgWith(0, fakeEl);
      emulateAttached();

      // Assert that onAttachedFunc is called and HTML elements have the
      // expected state.
      assert.isTrue(onAttachedFuncCalled);
      assert.equal(checkbox.id, 'annotation-checkbox');
      assert.isTrue(checkbox.disabled);
      assert.equal(document.getElementById('annotation-label').textContent,
          'test label');
      assert.isFalse(document.getElementById('annotation-span').hidden);

      // Assert that error is shown if we try to enable checkbox again.
      onAttachedFuncCalled = false;
      annotationActions.enableToggleCheckbox('test label2', onAttachedFunc);
      const errorStub = sandbox.stub(
          console, 'error', (msg, err) => undefined);
      emulateAttached();
      assert.isTrue(
          errorStub.calledWith(
              'annotation-span is already enabled. Cannot re-enable.'));
      // Assert that onAttachedFunc is not called and the label has not changed.
      assert.isFalse(onAttachedFuncCalled);
      assert.equal(document.getElementById('annotation-label').textContent,
          'test label');
    });

    test('layer notify listeners', () => {
      const annotationLayer = annotationActions.getLayer(
          '/dummy/path', 1, 2);
      let listenerCalledTimes = 0;
      const startRange = 10;
      const endRange = 20;
      const side = 'right';
      const listener = (st, end, s) => {
        listenerCalledTimes++;
        assert.equal(st, startRange);
        assert.equal(end, endRange);
        assert.equal(s, side);
      };

      // Notify with 0 listeners added.
      annotationLayer.notifyListeners(startRange, endRange, side);
      assert.equal(listenerCalledTimes, 0);

      // Add 1 listener.
      annotationLayer.addListener(listener);
      annotationLayer.notifyListeners(startRange, endRange, side);
      assert.equal(listenerCalledTimes, 1);

      // Add 1 more listener. Total 2 listeners.
      annotationLayer.addListener(listener);
      annotationLayer.notifyListeners(startRange, endRange, side);
      assert.equal(listenerCalledTimes, 3);
    });
  });
</script>
