<!DOCTYPE html>
<!--
@license
Copyright (C) 2019 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-admin-api</title>

<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>

<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
<script src="/components/wct-browser-legacy/browser.js"></script>

<dom-module id="gr-style-test-element">
  <template>
    <div id="wrapper"></div>
  </template>
  <script type="module">
import '../../../test/common-test-setup.js';
import '../../shared/gr-js-api-interface/gr-js-api-interface.js';
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
Polymer({is: 'gr-style-test-element'});
</script>
</dom-module>

<script type="module">
import '../../../test/common-test-setup.js';
import '../../shared/gr-js-api-interface/gr-js-api-interface.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit.js';

const pluginApi = _testOnly_initGerritPluginApi();

suite('gr-styles-api tests', () => {
  let sandbox;
  let stylesApi;

  setup(() => {
    sandbox = sinon.sandbox.create();
    let plugin;
    pluginApi.install(p => { plugin = p; }, '0.1',
        'http://test.com/plugins/testplugin/static/test.js');
    pluginLoader.loadPlugins([]);
    stylesApi = plugin.styles();
  });

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

  test('exists', () => {
    assert.isOk(stylesApi);
  });

  test('css', () => {
    const styleObject = stylesApi.css('background: red');
    assert.isDefined(styleObject);
  });

  suite('GrStyleObject tests', () => {
    let sandbox;
    let stylesApi;
    let displayInlineStyle;
    let displayNoneStyle;

    setup(() => {
      sandbox = sinon.sandbox.create();
      let plugin;
      pluginApi.install(p => { plugin = p; }, '0.1',
          'http://test.com/plugins/testplugin/static/test.js');
      pluginLoader.loadPlugins([]);
      stylesApi = plugin.styles();
      displayInlineStyle = stylesApi.css('display: inline');
      displayNoneStyle = stylesApi.css('display: none');
    });

    teardown(() => {
      displayInlineStyle = null;
      displayNoneStyle = null;
      stylesApi = null;
      sandbox.restore();
    });

    function createNestedElements(parentElement) {
      /* parentElement
      *  |--- element1
      *  |--- element2
      *       |--- element3
      **/
      const element1 = document.createElement('div');
      const element2 = document.createElement('div');
      const element3 = document.createElement('div');
      dom(parentElement).appendChild(element1);
      dom(parentElement).appendChild(element2);
      dom(element2).appendChild(element3);

      return [element1, element2, element3];
    }

    test('getClassName  - body level elements', () => {
      const bodyLevelElements = createNestedElements(document.body);

      testGetClassName(bodyLevelElements);
    });

    test('getClassName  - elements inside polymer element', () => {
      const polymerElement = document.createElement('gr-style-test-element');
      dom(document.body).appendChild(polymerElement);
      const contentElements = createNestedElements(polymerElement.$.wrapper);

      testGetClassName(contentElements);
    });

    function testGetClassName(elements) {
      assertAllElementsHaveDefaultStyle(elements);

      const className1 = displayInlineStyle.getClassName(elements[0]);
      const className2 = displayNoneStyle.getClassName(elements[1]);
      const className3 = displayInlineStyle.getClassName(elements[2]);

      assert.notEqual(className2, className1);
      assert.equal(className3, className1);

      assertAllElementsHaveDefaultStyle(elements);

      elements[0].classList.add(className1);
      elements[1].classList.add(className2);
      elements[2].classList.add(className1);

      assertDisplayPropertyValues(elements, ['inline', 'none', 'inline']);
    }

    test('apply - body level elements', () => {
      const bodyLevelElements = createNestedElements(document.body);

      testApply(bodyLevelElements);
    });

    test('apply - elements inside polymer element', () => {
      const polymerElement = document.createElement('gr-style-test-element');
      dom(document.body).appendChild(polymerElement);
      const contentElements = createNestedElements(polymerElement.$.wrapper);

      testApply(contentElements);
    });

    function testApply(elements) {
      assertAllElementsHaveDefaultStyle(elements);
      displayInlineStyle.apply(elements[0]);
      displayNoneStyle.apply(elements[1]);
      displayInlineStyle.apply(elements[2]);
      assertDisplayPropertyValues(elements, ['inline', 'none', 'inline']);
    }

    function assertAllElementsHaveDefaultStyle(elements) {
      for (const element of elements) {
        assert.equal(getComputedStyle(element).getPropertyValue('display'),
            'block');
      }
    }

    function assertDisplayPropertyValues(elements, expectedDisplayValues) {
      for (const key in elements) {
        if (elements.hasOwnProperty(key)) {
          assert.equal(
              getComputedStyle(elements[key]).getPropertyValue('display'),
              expectedDisplayValues[key]);
        }
      }
    }
  });
});
</script>
