<!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.
-->

<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>gr-dom-hooks</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="gr-dom-hooks.html"/>

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

<test-fixture id="basic">
  <template>
    <div></div>
  </template>
</test-fixture>

<script>
  suite('gr-dom-hooks tests', () => {
    const PUBLIC_METHODS =
        ['onAttached', 'getLastAttached', 'getAllAttached', 'getModuleName'];

    let instance;
    let sandbox;
    let hook;
    let hookInternal;

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

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

    suite('placeholder', () => {
      setup(()=>{
        sandbox.stub(GrDomHook.prototype, '_createPlaceholder');
        hookInternal = instance.getDomHook('foo-bar');
        hook = hookInternal.getPublicAPI();
      });

      test('public hook API has only public methods', () => {
        assert.deepEqual(Object.keys(hook), PUBLIC_METHODS);
      });

      test('registers placeholder class', () => {
        assert.isTrue(hookInternal._createPlaceholder.calledWithExactly(
            'testplugin-autogenerated-foo-bar'));
      });

      test('getModuleName()', () => {
        const hookName = Object.keys(instance._hooks).pop();
        assert.equal(hookName, 'testplugin-autogenerated-foo-bar');
        assert.equal(hook.getModuleName(), 'testplugin-autogenerated-foo-bar');
      });
    });

    suite('custom element', () => {
      setup(() => {
        hookInternal = instance.getDomHook('foo-bar', 'my-el');
        hook = hookInternal.getPublicAPI();
      });

      test('public hook API has only public methods', () => {
        assert.deepEqual(Object.keys(hook), PUBLIC_METHODS);
      });

      test('getModuleName()', () => {
        const hookName = Object.keys(instance._hooks).pop();
        assert.equal(hookName, 'foo-bar my-el');
        assert.equal(hook.getModuleName(), 'my-el');
      });

      test('onAttached', () => {
        const onAttachedSpy = sandbox.spy();
        hook.onAttached(onAttachedSpy);
        const [el1, el2] = [
          document.createElement(hook.getModuleName()),
          document.createElement(hook.getModuleName()),
        ];
        hookInternal.handleInstanceAttached(el1);
        hookInternal.handleInstanceAttached(el2);
        assert.isTrue(onAttachedSpy.firstCall.calledWithExactly(el1));
        assert.isTrue(onAttachedSpy.secondCall.calledWithExactly(el2));
      });

      test('getAllAttached', () => {
        const [el1, el2] = [
          document.createElement(hook.getModuleName()),
          document.createElement(hook.getModuleName()),
        ];
        el1.textContent = 'one';
        el2.textContent = 'two';
        hookInternal.handleInstanceAttached(el1);
        hookInternal.handleInstanceAttached(el2);
        assert.deepEqual([el1, el2], hook.getAllAttached());
        hookI.handleInstanceDetached(el1);
        assert.deepEqual([el2], hook.getAllAttached());
      });

      test('getLastAttached', () => {
        const beforeAttachedPromise = hook.getLastAttached().then(
            el => assert.strictEqual(el1, el));
        const [el1, el2] = [
          document.createElement(hook.getModuleName()),
          document.createElement(hook.getModuleName()),
        ];
        el1.textContent = 'one';
        el2.textContent = 'two';
        hookInternal.handleInstanceAttached(el1);
        hookInternal.handleInstanceAttached(el2);
        const afterAttachedPromise = hook.getLastAttached().then(
            el => assert.strictEqual(el2, el));
        return Promise.all([
          beforeAttachedPromise,
          afterAttachedPromise,
        ]);
      });
    });
  });
</script>
