chromium/chrome/test/data/webui/print_preview/destination_dropdown_cros_test.ts

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

import type {PrintPreviewDestinationDropdownCrosElement} from 'chrome://print/print_preview.js';
import {Destination, DestinationOrigin} from 'chrome://print/print_preview.js';
import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {keyDownOn} from 'chrome://webui-test/keyboard_mock_interactions.js';
import {move} from 'chrome://webui-test/mouse_mock_interactions.js';
import {eventToPromise} from 'chrome://webui-test/test_util.js';

import {getGoogleDriveDestination, getSaveAsPdfDestination} from './print_preview_test_utils.js';

suite('DestinationDropdownCrosTest', function() {
  let dropdown: PrintPreviewDestinationDropdownCrosElement;

  function setItemList(items: Destination[]) {
    dropdown.itemList = items;
    flush();
  }

  function getList(): HTMLButtonElement[] {
    return Array.from(
        dropdown.shadowRoot!.querySelectorAll<HTMLButtonElement>('.list-item'));
  }

  function clickDropdown() {
    dropdown.$.destinationDropdown.click();
  }

  function clickDropdownFocus() {
    dropdown.$.destinationDropdown.click();
    dropdown.$.destinationDropdown.focus();
  }

  function clickOutsideDropdown() {
    document.body.click();
    dropdown.$.destinationDropdown.blur();
  }

  function down() {
    keyDownOn(dropdown.$.destinationDropdown, 40, [], 'ArrowDown');
  }

  function up() {
    keyDownOn(dropdown.$.destinationDropdown, 38, [], 'ArrowUp');
  }

  function enter() {
    keyDownOn(dropdown.$.destinationDropdown, 13, [], 'Enter');
  }

  function getHighlightedElement(): (HTMLElement|null) {
    return dropdown.shadowRoot!.querySelector('.highlighted');
  }

  function getHighlightedElementText(): string {
    return getHighlightedElement()!.textContent!.trim();
  }

  function createDestination(
      displayName: string, destinationOrigin: DestinationOrigin): Destination {
    return new Destination(displayName, destinationOrigin, displayName);
  }

  setup(function() {
    document.body.innerHTML = window.trustedTypes!.emptyHTML;

    dropdown =
        document.createElement('print-preview-destination-dropdown-cros');
    document.body.appendChild(dropdown);
    dropdown.noDestinations = false;
    dropdown.driveDestinationKey = getGoogleDriveDestination().key;
    dropdown.pdfDestinationKey = getSaveAsPdfDestination().key;
  });

  test(
      'CorrectListItems', function() {
        setItemList([
          createDestination('One', DestinationOrigin.CROS),
          createDestination('Two', DestinationOrigin.CROS),
          createDestination('Three', DestinationOrigin.CROS),
        ]);

        const itemList = getList();
        assertEquals(7, itemList.length);
        assertEquals('One', itemList[0]!.textContent!.trim());
        assertEquals('Two', itemList[1]!.textContent!.trim());
        assertEquals('Three', itemList[2]!.textContent!.trim());
      });

  test('ClickCloses', function() {
    const destinationOne = createDestination('One', DestinationOrigin.CROS);
    setItemList([destinationOne]);
    dropdown.value = destinationOne;
    const ironDropdown = dropdown.shadowRoot!.querySelector('iron-dropdown')!;

    clickDropdownFocus();
    assertTrue(ironDropdown.opened);

    getList()[0]!.click();
    assertFalse(ironDropdown.opened);

    clickDropdownFocus();
    assertTrue(ironDropdown.opened);

    // Clicking outside the dropdown will cause it to lose focus and close.
    // This will verify on-blur closes the dropdown.
    clickOutsideDropdown();
    assertFalse(ironDropdown.opened);
  });

  test('HighlightedAfterUpDown', function() {
    const destinationOne = createDestination('One', DestinationOrigin.CROS);
    setItemList([destinationOne]);
    dropdown.value = destinationOne;
    clickDropdown();

    assertEquals('One', getHighlightedElementText());
    down();
    assertEquals('Save as PDF', getHighlightedElementText());
    down();
    assertEquals('Save to Google Drive', getHighlightedElementText());
    down();
    assertEquals('See more…', getHighlightedElementText());
    down();
    assertEquals('See more…', getHighlightedElementText());

    up();
    assertEquals('Save to Google Drive', getHighlightedElementText());
    up();
    assertEquals('Save as PDF', getHighlightedElementText());
    up();
    assertEquals('One', getHighlightedElementText());
    up();
    assertEquals('One', getHighlightedElementText());
  });

  test(
      'DestinationChangeAfterUpDown', function() {
        const destinationOne = createDestination('One', DestinationOrigin.CROS);
        const pdfDestination = getSaveAsPdfDestination();
        setItemList([destinationOne]);
        dropdown.value = pdfDestination;

        // Verify an up press sends |destinationOne| as the next value selected.
        const whenSelectedAfterUpPress =
            eventToPromise('dropdown-value-selected', dropdown);
        up();
        whenSelectedAfterUpPress.then(event => {
          assertEquals(destinationOne.key, event.detail.value);
        });

        // Key press does not directly update |value| so it is expected for the
        // |value| to not change here in this test.
        assertEquals(dropdown.value, pdfDestination);

        // Verify a down press sends the Save to Google Drive destination as the
        // next value selected.
        const whenSelectedAfterDownPress =
            eventToPromise('dropdown-value-selected', dropdown);
        down();
        whenSelectedAfterDownPress.then(event => {
          assertEquals(getGoogleDriveDestination().key, event.detail.value);
        });
      });

  test('EnterOpensCloses', function() {
    const destinationOne = createDestination('One', DestinationOrigin.CROS);
    setItemList([destinationOne]);
    dropdown.value = destinationOne;

    assertFalse(dropdown.shadowRoot!.querySelector('iron-dropdown')!.opened);
    enter();
    assertTrue(dropdown.shadowRoot!.querySelector('iron-dropdown')!.opened);
    enter();
    assertFalse(dropdown.shadowRoot!.querySelector('iron-dropdown')!.opened);
  });

  test(
      'HighlightedFollowsMouse', function() {
        const destinationOne = createDestination('One', DestinationOrigin.CROS);
        setItemList([
          destinationOne,
          createDestination('Two', DestinationOrigin.CROS),
          createDestination('Three', DestinationOrigin.CROS),
        ]);
        dropdown.value = destinationOne;
        clickDropdown();

        move(getList()[1]!, {x: 0, y: 0}, {x: 0, y: 0}, 1);
        assertEquals('Two', getHighlightedElementText());
        move(getList()[2]!, {x: 0, y: 0}, {x: 0, y: 0}, 1);
        assertEquals('Three', getHighlightedElementText());

        // Interacting with the keyboard should update the highlighted element.
        up();
        assertEquals('Two', getHighlightedElementText());

        // When the user moves the mouse again, the highlighted element should
        // change.
        move(getList()[0]!, {x: 0, y: 0}, {x: 0, y: 0}, 1);
        assertEquals('One', getHighlightedElementText());
      });

  test('Disabled', function() {
    const destinationOne = createDestination('One', DestinationOrigin.CROS);
    setItemList([destinationOne]);
    dropdown.value = destinationOne;
    dropdown.disabled = true;

    clickDropdown();
    assertFalse(dropdown.shadowRoot!.querySelector('iron-dropdown')!.opened);
    assertEquals('-1', dropdown.$.destinationDropdown.getAttribute('tabindex'));

    dropdown.disabled = false;
    clickDropdown();
    assertTrue(dropdown.shadowRoot!.querySelector('iron-dropdown')!.opened);
    assertEquals('0', dropdown.$.destinationDropdown.getAttribute('tabindex'));
  });

  test(
      'HighlightedWhenOpened', function() {
        const destinationTwo = createDestination('Two', DestinationOrigin.CROS);
        const destinationThree =
            createDestination('Three', DestinationOrigin.CROS);
        setItemList([
          createDestination('One', DestinationOrigin.CROS),
          destinationTwo,
          destinationThree,
        ]);

        dropdown.value = destinationTwo;
        clickDropdown();
        assertEquals('Two', getHighlightedElementText());
        clickDropdown();

        dropdown.value = destinationThree;
        clickDropdown();
        assertEquals('Three', getHighlightedElementText());
      });
});