chromium/chrome/test/data/webui/chromeos/settings/os_settings_menu/os_settings_menu_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.

import 'chrome://os-settings/os_settings.js';

import {createPageAvailabilityForTesting, IronCollapseElement, IronSelectorElement, OsSettingsMenuElement, Router, routes, routesMojom} from 'chrome://os-settings/os_settings.js';
import {IronIconElement} from 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {isVisible} from 'chrome://webui-test/test_util.js';

/** @fileoverview Runs tests for the OS settings menu. */
suite('<os-settings-menu>', () => {
  let settingsMenu: OsSettingsMenuElement;

  setup(() => {
    settingsMenu = document.createElement('os-settings-menu');
    settingsMenu.pageAvailability = createPageAvailabilityForTesting();
    document.body.appendChild(settingsMenu);
    flush();
  });

  teardown(() => {
    settingsMenu.remove();
    Router.getInstance().resetRouteForTesting();
  });

  test('advancedOpenedBinding', () => {
    assertFalse(settingsMenu.advancedOpened);
    settingsMenu.advancedOpened = true;
    flush();

    const advancedCollapse =
        settingsMenu.shadowRoot!.querySelector<IronCollapseElement>(
            '#advancedCollapse');
    assertTrue(!!advancedCollapse);
    assertTrue(advancedCollapse.opened);

    settingsMenu.advancedOpened = false;
    flush();
    assertFalse(advancedCollapse.opened);
  });

  test('tapAdvanced', () => {
    assertFalse(settingsMenu.advancedOpened);

    const advancedToggle =
        settingsMenu.shadowRoot!.querySelector<HTMLButtonElement>(
            '#advancedButton');
    assertTrue(!!advancedToggle);

    advancedToggle.click();
    flush();

    const advancedCollapse =
        settingsMenu.shadowRoot!.querySelector<IronCollapseElement>(
            '#advancedCollapse');
    assertTrue(!!advancedCollapse);
    assertTrue(advancedCollapse.opened);

    advancedToggle.click();
    flush();
    assertFalse(advancedCollapse.opened);
  });

  test('upAndDownIcons', () => {
    // There should be different icons for a top level menu being open
    // vs. being closed. E.g. arrow-drop-up and arrow-drop-down.
    const ironIconElement =
        settingsMenu.shadowRoot!.querySelector<IronIconElement>(
            '#advancedButton iron-icon');
    assertTrue(!!ironIconElement);

    settingsMenu.advancedOpened = true;
    flush();
    const openIcon = ironIconElement.icon;
    assertTrue(!!openIcon);

    settingsMenu.advancedOpened = false;
    flush();
    assertNotEquals(openIcon, ironIconElement.icon);
  });

  test('Advanced menu expands on navigating to an advanced setting', () => {
    assertFalse(settingsMenu.advancedOpened);
    Router.getInstance().navigateTo(routes.OS_RESET);
    assertFalse(settingsMenu.advancedOpened);

    // If there are search params and the current route is a descendant of
    // the Advanced route, then ensure that the advanced menu expands.
    const params = new URLSearchParams('search=test');
    Router.getInstance().navigateTo(routes.OS_RESET, params);
    flush();
    assertTrue(settingsMenu.advancedOpened);
  });
});

suite('<os-settings-menu> reset', () => {
  let settingsMenu: OsSettingsMenuElement;

  setup(() => {
    Router.getInstance().navigateTo(routes.OS_RESET);
    settingsMenu = document.createElement('os-settings-menu');
    settingsMenu.pageAvailability = createPageAvailabilityForTesting();
    document.body.appendChild(settingsMenu);
    flush();
  });

  teardown(() => {
    settingsMenu.remove();
    Router.getInstance().resetRouteForTesting();
  });

  test('openResetSection', () => {
    const submenu = settingsMenu.shadowRoot!.querySelector<IronSelectorElement>(
        '#advancedSubmenu');
    assertTrue(!!submenu);
    const path = submenu.selected;
    assertEquals('/osReset', path);
  });

  test('navigateToAnotherSection', () => {
    const submenu = settingsMenu.shadowRoot!.querySelector<IronSelectorElement>(
        '#advancedSubmenu');
    assertTrue(!!submenu);
    let path = submenu.selected;
    assertEquals('/osReset', path);

    Router.getInstance().navigateTo(routes.BLUETOOTH);
    flush();

    path = submenu.selected;
    assertEquals('/bluetooth', path);
  });

  test('navigateToBasic', () => {
    const submenu = settingsMenu.shadowRoot!.querySelector<IronSelectorElement>(
        '#advancedSubmenu');
    assertTrue(!!submenu);
    const path = submenu.selected;
    assertEquals('/osReset', path);

    Router.getInstance().navigateTo(routes.BASIC);
    flush();

    // BASIC has no sub page selected.
    assertEquals('', submenu.selected);
  });
});

suite('<os-settings-menu> menu item visibility', () => {
  let settingsMenu: OsSettingsMenuElement;

  const {Section} = routesMojom;
  type SectionName = keyof typeof Section;

  setup(() => {
    settingsMenu = document.createElement('os-settings-menu');
    settingsMenu.pageAvailability = createPageAvailabilityForTesting();
    settingsMenu.advancedOpened = true;
    document.body.appendChild(settingsMenu);
    flush();
  });

  teardown(() => {
    settingsMenu.remove();
  });

  function queryMenuItemByPath(path: string): HTMLElement|null {
    return settingsMenu.shadowRoot!.querySelector<HTMLElement>(
        `os-settings-menu-item[path="${path}"]`);
  }

  test('About page menu item should always be visible', () => {
    const path = `/${routesMojom.ABOUT_CHROME_OS_SECTION_PATH}`;
    const menuItem = queryMenuItemByPath(path);
    assertTrue(isVisible(menuItem));
  });

  interface MenuItemData {
    sectionName: SectionName;
    path: string;
  }

  const menuItemData: MenuItemData[] = [
    // Basic pages
    {
      sectionName: 'kNetwork',
      path: `/${routesMojom.NETWORK_SECTION_PATH}`,
    },
    {
      sectionName: 'kBluetooth',
      path: `/${routesMojom.BLUETOOTH_SECTION_PATH}`,
    },
    {
      sectionName: 'kMultiDevice',
      path: `/${routesMojom.MULTI_DEVICE_SECTION_PATH}`,
    },
    {
      sectionName: 'kPeople',
      path: `/${routesMojom.PEOPLE_SECTION_PATH}`,
    },
    {
      sectionName: 'kKerberos',
      path: `/${routesMojom.KERBEROS_SECTION_PATH}`,
    },
    {
      sectionName: 'kDevice',
      path: `/${routesMojom.DEVICE_SECTION_PATH}`,
    },
    {
      sectionName: 'kPersonalization',
      path: `/${routesMojom.PERSONALIZATION_SECTION_PATH}`,
    },
    {
      sectionName: 'kSearchAndAssistant',
      path: `/${routesMojom.SEARCH_AND_ASSISTANT_SECTION_PATH}`,
    },
    {
      sectionName: 'kPrivacyAndSecurity',
      path: `/${routesMojom.PRIVACY_AND_SECURITY_SECTION_PATH}`,
    },
    {
      sectionName: 'kApps',
      path: `/${routesMojom.APPS_SECTION_PATH}`,
    },
    {
      sectionName: 'kAccessibility',
      path: `/${routesMojom.ACCESSIBILITY_SECTION_PATH}`,
    },

    // Advanced pages
    {
      sectionName: 'kDateAndTime',
      path: `/${routesMojom.DATE_AND_TIME_SECTION_PATH}`,
    },
    {
      sectionName: 'kLanguagesAndInput',
      path: `/${routesMojom.LANGUAGES_AND_INPUT_SECTION_PATH}`,
    },
    {
      sectionName: 'kFiles',
      path: `/${routesMojom.FILES_SECTION_PATH}`,
    },
    {
      sectionName: 'kPrinting',
      path: `/${routesMojom.PRINTING_SECTION_PATH}`,
    },
    {
      sectionName: 'kCrostini',
      path: `/${routesMojom.CROSTINI_SECTION_PATH}`,
    },
    {
      sectionName: 'kReset',
      path: `/${routesMojom.RESET_SECTION_PATH}`,
    },
  ];

  for (const {sectionName, path} of menuItemData) {
    test(
        `${sectionName} menu item is visible if page is available`, () => {
          // Make page available
          settingsMenu.pageAvailability = {
            ...settingsMenu.pageAvailability,
            [Section[sectionName]]: true,
          };
          flush();

          const menuItem = queryMenuItemByPath(path);
          assertTrue(isVisible(menuItem));
        });


    test(
        `${sectionName} menu item is not visible if page is unavailable`,
        () => {
          // Make page unavailable
          settingsMenu.pageAvailability = {
            ...settingsMenu.pageAvailability,
            [Section[sectionName]]: false,
          };
          flush();

          const menuItem = queryMenuItemByPath(path);
          assertFalse(isVisible(menuItem));
        });
  }
});