chromium/chrome/test/data/webui/chromeos/ash_common/cr_elements/cr_view_manager_test.ts

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// clang-format off
import 'chrome://resources/ash/common/cr_elements/cr_view_manager/cr_view_manager.js';

import {CrViewManagerElement} from 'chrome://resources/ash/common/cr_elements/cr_view_manager/cr_view_manager.js';
import {getTrustedHTML} from 'chrome://resources/js/static_types.js';
import {assertEquals} from 'chrome://webui-test/chai_assert.js';
import {isChildVisible} from 'chrome://webui-test/test_util.js';
// clang-format on


/** @fileoverview Suite of tests for cr-view-manager. */
/** @enum {string} */
enum TestNames {
  VISIBILITY = 'visibility',
  EVENT_FIRING = 'event firing',
}

let viewManager: CrViewManagerElement;
let parent: HTMLElement;

const suiteName = 'CrElementsViewManagerTest';

suite(suiteName, function() {
  // Initialize an cr-view-manager inside a parent div before
  // each test.
  setup(function() {
    document.body.innerHTML = getTrustedHTML`
        <div id="parent">
          <cr-view-manager id="viewManager">
            <div slot="view" id="viewOne">view 1</div>
            <div slot="view" id="viewTwo">view 2</div>
            <div slot="view" id="viewThree">view 3</div>
          </cr-view-manager>
        </div>
      `;
    parent = document.body.querySelector('#parent')!;
    viewManager = document.body.querySelector('#viewManager')!;
  });

  test(TestNames.VISIBILITY, function() {
    function assertViewVisible(id: string, expectIsVisible: boolean) {
      assertEquals(
          expectIsVisible,
          isChildVisible(viewManager, `#${id}`, /*checkLightDom=*/ true));
    }

    assertViewVisible('viewOne', false);
    assertViewVisible('viewTwo', false);
    assertViewVisible('viewThree', false);

    return viewManager.switchView('viewOne')
        .then(() => {
          assertViewVisible('viewOne', true);
          assertViewVisible('viewTwo', false);
          assertViewVisible('viewThree', false);

          return viewManager.switchView('viewThree');
        })
        .then(() => {
          assertViewVisible('viewOne', false);
          assertViewVisible('viewTwo', false);
          assertViewVisible('viewThree', true);
        });
  });

  test(TestNames.EVENT_FIRING, function() {
    const viewOne = viewManager.querySelector('#viewOne')!;

    let fired = new Set();
    let bubbled = new Set();

    ['view-enter-start',
     'view-enter-finish',
     'view-exit-start',
     'view-exit-finish',
    ].forEach(type => {
      parent.addEventListener(type, () => {
        bubbled.add(type);
      });
      viewOne.addEventListener(type, () => {
        fired.add(type);
      });
    });

    /**
     * @param eventName The event to check
     * @param expectFired Whether the event should have fired.
     */
    function verifyEventFiredAndBubbled(
        eventName: string, expectFired: boolean) {
      assertEquals(expectFired, fired.has(eventName));
      assertEquals(expectFired, bubbled.has(eventName));
    }

    // Initial switch has no animation.
    viewManager.switchView('viewOne');
    // view-enter-start and view-enter-finish are fired synchronously when
    // there's no animation.
    verifyEventFiredAndBubbled('view-enter-start', true);
    verifyEventFiredAndBubbled('view-enter-finish', true);

    const exitPromises = viewManager.switchView('viewTwo');
    verifyEventFiredAndBubbled('view-exit-start', true);
    // view-exit-finish is waiting on the animation.
    verifyEventFiredAndBubbled('view-exit-finish', false);

    return exitPromises
        .then(() => {
          verifyEventFiredAndBubbled('view-exit-finish', true);

          fired = new Set();
          bubbled = new Set();

          // Switching back has an animation this time.
          const enterPromises = viewManager.switchView('viewOne');
          verifyEventFiredAndBubbled('view-enter-start', true);
          verifyEventFiredAndBubbled('view-enter-finish', false);
          return enterPromises;
        })
        .then(() => {
          verifyEventFiredAndBubbled('view-enter-finish', true);
        });
  });
});