<!DOCTYPE html>
<!--
@license
Copyright (C) 2017 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.
-->

<title>tooltip-behavior</title>

<script src="../../bower_components/webcomponentsjs/webcomponents.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="gr-tooltip-behavior.html">

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

<test-fixture id="basic">
  <template>
    <tooltip-behavior-element></tooltip-behavior-element>
  </template>
</test-fixture>

<script>
  suite('gr-tooltip-behavior tests', () => {
    let element;
    let sandbox;

    function makeTooltip(tooltipRect, parentRect) {
      return {
        getBoundingClientRect() { return tooltipRect; },
        updateStyles: sinon.stub(),
        style: {left: 0, top: 0},
        parentElement: {
          getBoundingClientRect() { return parentRect; },
        },
      };
    }

    suiteSetup(() => {
      // Define a Polymer element that uses this behavior.
      Polymer({
        is: 'tooltip-behavior-element',
        _legacyUndefinedCheck: true,
        behaviors: [Gerrit.TooltipBehavior],
      });
    });

    setup(() => {
      sandbox = sinon.sandbox.create();
      element = fixture('basic');
    });

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

    test('normal position', () => {
      sandbox.stub(element, 'getBoundingClientRect', () => {
        return {top: 100, left: 100, width: 200};
      });
      const tooltip = makeTooltip(
          {height: 30, width: 50},
          {top: 0, left: 0, width: 1000});

      element._positionTooltip(tooltip);
      assert.isFalse(tooltip.updateStyles.called);
      assert.equal(tooltip.style.left, '175px');
      assert.equal(tooltip.style.top, '100px');
    });

    test('left side position', () => {
      sandbox.stub(element, 'getBoundingClientRect', () => {
        return {top: 100, left: 10, width: 50};
      });
      const tooltip = makeTooltip(
          {height: 30, width: 120},
          {top: 0, left: 0, width: 1000});

      element._positionTooltip(tooltip);
      assert.isTrue(tooltip.updateStyles.called);
      const offset = tooltip.updateStyles
          .lastCall.args[0]['--gr-tooltip-arrow-center-offset'];
      assert.isBelow(parseFloat(offset.replace(/px$/, '')), 0);
      assert.equal(tooltip.style.left, '0px');
      assert.equal(tooltip.style.top, '100px');
    });

    test('right side position', () => {
      sandbox.stub(element, 'getBoundingClientRect', () => {
        return {top: 100, left: 950, width: 50};
      });
      const tooltip = makeTooltip(
          {height: 30, width: 120},
          {top: 0, left: 0, width: 1000});

      element._positionTooltip(tooltip);
      assert.isTrue(tooltip.updateStyles.called);
      const offset = tooltip.updateStyles
          .lastCall.args[0]['--gr-tooltip-arrow-center-offset'];
      assert.isAbove(parseFloat(offset.replace(/px$/, '')), 0);
      assert.equal(tooltip.style.left, '915px');
      assert.equal(tooltip.style.top, '100px');
    });

    test('position to bottom', () => {
      sandbox.stub(element, 'getBoundingClientRect', () => {
        return {top: 100, left: 950, width: 50, height: 50};
      });
      const tooltip = makeTooltip(
          {height: 30, width: 120},
          {top: 0, left: 0, width: 1000});

      element.positionBelow = true;
      element._positionTooltip(tooltip);
      assert.isTrue(tooltip.updateStyles.called);
      const offset = tooltip.updateStyles
          .lastCall.args[0]['--gr-tooltip-arrow-center-offset'];
      assert.isAbove(parseFloat(offset.replace(/px$/, '')), 0);
      assert.equal(tooltip.style.left, '915px');
      assert.equal(tooltip.style.top, '157.2px');
    });

    test('hides tooltip when detached', () => {
      sandbox.stub(element, '_handleHideTooltip');
      element.remove();
      flushAsynchronousOperations();
      assert.isTrue(element._handleHideTooltip.called);
    });

    test('sets up listeners when has-tooltip is changed', () => {
      const addListenerStub = sandbox.stub(element, 'addEventListener');
      element.hasTooltip = true;
      assert.isTrue(addListenerStub.called);
    });
  });
</script>
