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

// Copyright 2019 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_button/cr_button.js';

import {getTrustedHTML} from 'chrome://resources/js/static_types.js';
import {CrButtonElement} from 'chrome://resources/ash/common/cr_elements/cr_button/cr_button.js';
import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {eventToPromise} from 'chrome://webui-test/test_util.js';

// clang-format on

suite('cr-button', function() {
  let button: CrButtonElement;

  setup(() => {
    document.body.innerHTML = window.trustedTypes!.emptyHTML;
    button =
        /** @type {!CrButtonElement} */ (document.createElement('cr-button'));
    document.body.appendChild(button);
  });

  function press(key: string) {
    button.dispatchEvent(new KeyboardEvent('keydown', {key}));
    button.dispatchEvent(new KeyboardEvent('keyup', {key}));
  }

  test('label is displayed', async () => {
    const widthWithoutLabel = button.offsetWidth;
    document.body.innerHTML = getTrustedHTML`<cr-button>Long Label</cr-button>`;
    button = document.body.querySelector('cr-button')!;
    assertTrue(widthWithoutLabel < button.offsetWidth);
  });

  test('tabindex and aria-disabled', () => {
    assertFalse(button.disabled);
    assertFalse(button.hasAttribute('disabled'));
    assertEquals('0', button.getAttribute('tabindex'));
    assertEquals('false', button.getAttribute('aria-disabled'));
    button.disabled = true;
    assertTrue(button.hasAttribute('disabled'));
    assertEquals('-1', button.getAttribute('tabindex'));
    assertEquals('true', button.getAttribute('aria-disabled'));
  });

  test('enter/space/click events and programmatic click() calls', async () => {
    let clickCount = 0;
    function clickHandler() {
      clickCount++;
    }
    button.addEventListener('click', clickHandler);

    function checkClicks(expectedCount: number) {
      clickCount = 0;
      press('Enter');
      press(' ');
      button.dispatchEvent(new MouseEvent('click'));
      button.click();
      assertEquals(expectedCount, clickCount);
    }

    checkClicks(4);
    button.disabled = true;
    checkClicks(0);
    button.disabled = false;
    checkClicks(4);

    button.removeEventListener('click', clickHandler);
  });

  test('when tabindex is -1, it stays -1', async () => {
    document.body.innerHTML =
        getTrustedHTML`<cr-button custom-tab-index="-1"></cr-button>`;
    button = document.body.querySelector('cr-button')!;
    assertEquals('-1', button.getAttribute('tabindex'));
    button.disabled = true;
    assertEquals('-1', button.getAttribute('tabindex'));
    button.disabled = false;
    assertEquals('-1', button.getAttribute('tabindex'));
  });

  test('tabindex update', async () => {
    document.body.innerHTML = window.trustedTypes!.emptyHTML;
    button = document.createElement('cr-button');
    document.body.appendChild(button);
    assertEquals('0', button.getAttribute('tabindex'));
    button.customTabIndex = 1;
    assertEquals('1', button.getAttribute('tabindex'));
  });

  test('hidden', () => {
    assertFalse(button.hidden);
    assertFalse(button.hasAttribute('hidden'));
    assertNotEquals('none', getComputedStyle(button).display);
    button.hidden = true;
    assertTrue(button.hasAttribute('hidden'));
    assertEquals('none', getComputedStyle(button).display);
    button.hidden = false;
    assertFalse(button.hasAttribute('hidden'));
    assertNotEquals('none', getComputedStyle(button).display);
  });

  test('space up does not click without space down', () => {
    let clicked = false;
    button.addEventListener('click', () => {
      clicked = true;
    }, {once: true});
    button.dispatchEvent(new KeyboardEvent('keyup', {key: ' '}));
    assertFalse(clicked);
    press(' ');
    assertTrue(clicked);
  });

  test('space up events will not result in one click if loses focus', () => {
    let clicked = false;
    button.addEventListener('click', () => {
      clicked = true;
    }, {once: true});
    button.dispatchEvent(new KeyboardEvent('keydown', {key: ' '}));
    button.dispatchEvent(new Event('blur'));
    button.dispatchEvent(new KeyboardEvent('keyup', {key: ' '}));
    assertFalse(clicked);
    press(' ');
    assertTrue(clicked);
  });

  test('UpdatesStyleWithIcons', async () => {
    const buttonStyle = window.getComputedStyle(button);
    const whenPrefixSlotchange =
        eventToPromise('slotchange', button.$.prefixIcon);
    const icon = document.createElement('div');
    icon.slot = 'prefix-icon';
    button.appendChild(icon);

    const text = document.createTextNode('Hello world');
    button.appendChild(text);
    await whenPrefixSlotchange;

    assertEquals('8px', buttonStyle.gap);
    assertEquals('8px', buttonStyle.padding);

    document.documentElement.toggleAttribute('chrome-refresh-2023', true);
    assertEquals('8px 16px 8px 12px', buttonStyle.padding);
    document.documentElement.removeAttribute('chrome-refresh-2023');

    const whenPrefixSlotRemoved =
        eventToPromise('slotchange', button.$.prefixIcon);
    icon.remove();
    await whenPrefixSlotRemoved;

    assertEquals('normal', buttonStyle.gap);
    assertEquals('8px 16px', buttonStyle.padding);

    const whenSuffixSlotchange =
        eventToPromise('slotchange', button.$.suffixIcon);
    icon.slot = 'suffix-icon';
    button.appendChild(icon);
    await whenSuffixSlotchange;

    assertEquals('8px', buttonStyle.gap);
    assertEquals('8px', buttonStyle.padding);

    document.documentElement.toggleAttribute('chrome-refresh-2023', true);
    assertEquals('8px 12px 8px 16px', buttonStyle.padding);
    document.documentElement.removeAttribute('chrome-refresh-2023');
  });
});