chromium/chrome/test/data/webui/compose/compose_animator_test.ts

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

import 'chrome-untrusted://compose/animations/animator.js';

import {getTrustedHTML} from '//resources/js/static_types.js';
import {Animator} from 'chrome-untrusted://compose/animations/animator.js';
import {assertEquals} from 'chrome-untrusted://webui-test/chai_assert.js';

suite('ComposeAnimator', () => {
  let animator: Animator;
  let mockRoot: HTMLElement;

  function animationsAsPromises(animations: Animation[]) {
    return Promise.all(animations.map(animation => animation.finished));
  }

  setup(() => {
    document.body.innerHTML = window.trustedTypes!.emptyHTML;
    mockRoot = document.createElement('custom-element');
    const shadowRoot = mockRoot.attachShadow({mode: 'open'});
    shadowRoot.innerHTML = getTrustedHTML`
      <div class="child" id="child1"></div>
      <div class="child" id="child2"></div>
    `;
    document.body.appendChild(mockRoot);
    animator = new Animator(mockRoot, /* animationsEnabled= */ true);
  });

  test('Animates', async () => {
    const animations = animator.animate(
        '.child',
        [
          {width: '50px'},
          {width: '100px'},
        ],
        {delay: 10, duration: 50, easing: 'ease-in', fill: 'both'});
    assertEquals(2, animations.length);
    await animationsAsPromises(animations);
    animations.forEach((animation) => {
      const effect = animation.effect as KeyframeEffect;
      const timing = effect.getTiming();
      assertEquals(10, timing.delay);
      assertEquals(50, timing.duration);
      assertEquals('ease-in', timing.easing);
      assertEquals(100, (effect.target as HTMLElement).offsetWidth);
    });
  });

  test('FadesIn', async () => {
    const animations = animator.fadeIn('#child1', {duration: 5, fill: 'both'});
    assertEquals(1, animations.length);
    const child = mockRoot.shadowRoot!.querySelector('#child1')!;
    assertEquals('0', window.getComputedStyle(child).opacity);
    await animationsAsPromises(animations);
    assertEquals('1', window.getComputedStyle(child).opacity);
  });

  test('FadesOut', async () => {
    const animations = animator.fadeOut('#child1', {duration: 5, fill: 'both'});
    assertEquals(1, animations.length);
    const child = mockRoot.shadowRoot!.querySelector('#child1')!;
    assertEquals('1', window.getComputedStyle(child).opacity);
    await animationsAsPromises(animations);
    assertEquals('0', window.getComputedStyle(child).opacity);
    assertEquals('block', window.getComputedStyle(child).display);
  });

  test('FadesOutAndHides', async () => {
    const animations =
        animator.fadeOutAndHide('#child1', 'flex', {duration: 5, fill: 'both'});
    assertEquals(1, animations.length);
    const child = mockRoot.shadowRoot!.querySelector('#child1')!;
    assertEquals('1', window.getComputedStyle(child).opacity);
    assertEquals('flex', window.getComputedStyle(child).display);
    await animationsAsPromises(animations);
    assertEquals('0', window.getComputedStyle(child).opacity);
    assertEquals('none', window.getComputedStyle(child).display);
  });

  test('ScalesIn', async () => {
    const animations = animator.scaleIn('#child1', {duration: 5, fill: 'both'});
    assertEquals(1, animations.length);
    const child = mockRoot.shadowRoot!.querySelector('#child1')!;
    assertEquals(
        'matrix(0, 0, 0, 0, 0, 0)', window.getComputedStyle(child).transform);
    await animationsAsPromises(animations);
    assertEquals(
        'matrix(1, 0, 0, 1, 0, 0)', window.getComputedStyle(child).transform);
  });

  test('SlidesIn', async () => {
    const animations =
        animator.slideIn('#child1', 83, {duration: 5, fill: 'both'});
    assertEquals(1, animations.length);
    const child = mockRoot.shadowRoot!.querySelector('#child1')!;
    assertEquals(
        'matrix(1, 0, 0, 1, 0, 83)', window.getComputedStyle(child).transform);
    await animationsAsPromises(animations);
    assertEquals(
        'matrix(1, 0, 0, 1, 0, 0)', window.getComputedStyle(child).transform);
  });

  test('SlidesOut', async () => {
    const animations =
        animator.slideOut('#child1', 83, {duration: 5, fill: 'both'});
    assertEquals(1, animations.length);
    const child = mockRoot.shadowRoot!.querySelector('#child1')!;
    assertEquals(
        'matrix(1, 0, 0, 1, 0, 0)', window.getComputedStyle(child).transform);
    await animationsAsPromises(animations);
    assertEquals(
        'matrix(1, 0, 0, 1, 0, 83)', window.getComputedStyle(child).transform);
  });

  test('DisablesAnimations', () => {
    const disabledAnimator = new Animator(mockRoot, false);
    const animations = disabledAnimator.animate(
        '.child',
        [
          {width: '50px'},
          {width: '100px'},
        ],
        {delay: 10, duration: 50, easing: 'ease-in'});
    assertEquals(0, animations.length);
  });

  test('RequiresConditionMet', () => {
    const animations = animator.animate(
        '.child',
        [
          {width: '50px'},
          {width: '100px'},
        ],
        {duration: 100},
        /* falsey condition should mean no animations */ false);
    assertEquals(0, animations.length);
  });
});