chromium/chrome/test/data/webui/chromeos/settings/os_settings_ui/os_settings_ui_menu_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://os-settings/os_settings.js';

import {AccountManagerBrowserProxyImpl} from 'chrome://os-settings/lazy_load.js';
import {CrDrawerElement, CrSettingsPrefs, OsSettingsMenuElement, OsSettingsUiElement, Router, routes, routesMojom, setNearbyShareSettingsForTesting} from 'chrome://os-settings/os_settings.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
import {DomIf, flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {assertEquals, assertFalse, assertNull, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {FakeNearbyShareSettings} from 'chrome://webui-test/nearby_share/shared/fake_nearby_share_settings.js';
import {eventToPromise} from 'chrome://webui-test/test_util.js';

import {TestAccountManagerBrowserProxy} from '../os_people_page/test_account_manager_browser_proxy.js';

suite('<os-settings-ui> menu', () => {
  const isRevampWayfindingEnabled =
      loadTimeData.getBoolean('isRevampWayfindingEnabled');
  let ui: OsSettingsUiElement;
  let fakeNearbySettings: FakeNearbyShareSettings;
  let testAccountManagerBrowserProxy: TestAccountManagerBrowserProxy;

  suiteSetup(() => {
    fakeNearbySettings = new FakeNearbyShareSettings();
    setNearbyShareSettingsForTesting(fakeNearbySettings);

    // Setup fake accounts.
    testAccountManagerBrowserProxy = new TestAccountManagerBrowserProxy();
    AccountManagerBrowserProxyImpl.setInstanceForTesting(
        testAccountManagerBrowserProxy);
  });

  async function createElement(): Promise<OsSettingsUiElement> {
    const element = document.createElement('os-settings-ui');
    document.body.appendChild(element);
    await CrSettingsPrefs.initialized;
    flush();
    return element;
  }

  teardown(() => {
    ui.remove();
    Router.getInstance().resetRouteForTesting();
    testAccountManagerBrowserProxy.reset();
  });

  test('Drawer can open and close', async () => {
    ui = await createElement();

    const drawer = ui.shadowRoot!.querySelector<CrDrawerElement>('#drawer');
    assertTrue(!!drawer);
    assertFalse(drawer.open);

    let menu = ui.shadowRoot!.querySelector('#drawer os-settings-menu');
    assertNull(menu);

    drawer.openDrawer();
    flush();
    await eventToPromise('cr-drawer-opened', drawer);

    // Validate that dialog is open and menu is shown so it will animate.
    assertTrue(drawer.open);
    menu = ui.shadowRoot!.querySelector('#drawer os-settings-menu');
    assertTrue(!!menu);

    drawer.cancel();
    // Drawer is closed, but menu is still stamped so its contents remain
    // visible as the drawer slides out.
    menu = ui.shadowRoot!.querySelector('#drawer os-settings-menu');
    assertTrue(!!menu);
  });

  test('Drawer closes when exiting narrow mode', async () => {
    ui = await createElement();
    const drawer = ui.shadowRoot!.querySelector<CrDrawerElement>('#drawer');
    assertTrue(!!drawer);

    // Mimic narrow mode and open the drawer.
    ui.set('isNarrow', true);
    drawer.openDrawer();
    flush();
    await eventToPromise('cr-drawer-opened', drawer);
    assertTrue(drawer.open);

    // Mimic exiting narrow mode and confirm the drawer is closed
    ui.set('isNarrow', false);
    flush();
    await eventToPromise('close', drawer);
    assertFalse(drawer.open);
  });

  test('Navigating via menu clears current search URL param', async () => {
    ui = await createElement();
    const settingsMenu = ui.shadowRoot!.querySelector('os-settings-menu');
    assertTrue(!!settingsMenu);

    // As of iron-selector 2.x, need to force iron-selector to update before
    // clicking items on it, or wait for 'iron-items-changed'
    const ironSelector =
        settingsMenu.shadowRoot!.querySelector('iron-selector');
    assertTrue(!!ironSelector);
    ironSelector.forceSynchronousItemUpdate();

    const urlParams = new URLSearchParams('search=foo');
    const router = Router.getInstance();
    router.navigateTo(routes.BASIC, urlParams);
    assertEquals(urlParams.toString(), router.getQueryParameters().toString());
    const personalizationPath = `/${routesMojom.PERSONALIZATION_SECTION_PATH}`;
    const link = settingsMenu.shadowRoot!.querySelector<HTMLAnchorElement>(
        `os-settings-menu-item[path="${personalizationPath}"]`);
    assertTrue(!!link);
    link.click();
    assertEquals('', router.getQueryParameters().toString());
  });

  if (!isRevampWayfindingEnabled) {
    test('Advanced section in menu and main page behavior', async () => {
      ui = await createElement();
      const drawerTemplate =
          ui.shadowRoot!.querySelector<DomIf>('#drawerTemplate');
      assertTrue(!!drawerTemplate);
      drawerTemplate.if = true;
      flush();

      const main = ui.shadowRoot!.querySelector('os-settings-main');
      assertTrue(!!main);
      const mainPageContainer =
          main.shadowRoot!.querySelector('main-page-container');
      assertTrue(!!mainPageContainer);
      const mainPageAdvancedToggle =
          mainPageContainer.shadowRoot!.querySelector<HTMLButtonElement>(
              '#advancedToggle');
      assertTrue(!!mainPageAdvancedToggle);
      const floatingMenu = ui.shadowRoot!.querySelector<OsSettingsMenuElement>(
          '#left os-settings-menu');
      assertTrue(!!floatingMenu);
      const drawerMenu = ui.shadowRoot!.querySelector<OsSettingsMenuElement>(
          '#drawer os-settings-menu');
      assertTrue(!!drawerMenu);

      // Advanced section should not be expanded
      assertFalse(main.advancedToggleExpanded);
      assertFalse(drawerMenu.advancedOpened);
      assertFalse(floatingMenu.advancedOpened);

      mainPageAdvancedToggle.click();
      flush();

      // Advanced section should be expanded
      assertTrue(main.advancedToggleExpanded);
      assertTrue(drawerMenu.advancedOpened);
      assertTrue(floatingMenu.advancedOpened);

      // Collapse 'Advanced' in the menu.
      const advancedButton =
          drawerMenu.shadowRoot!.querySelector<HTMLButtonElement>(
              '#advancedButton');
      assertTrue(!!advancedButton);
      advancedButton.click();
      flush();

      // Collapsing it in the menu should not collapse it in the main area.
      assertTrue(main.advancedToggleExpanded);
      assertFalse(drawerMenu.advancedOpened);
      assertFalse(floatingMenu.advancedOpened);

      // Expand both 'Advanced's again.
      advancedButton.click();
      flush();

      // Collapse 'Advanced' in the main area.
      main.set('advancedToggleExpanded', false);
      flush();

      // Collapsing it in the main area should not collapse it in the menu.
      assertTrue(drawerMenu.advancedOpened);
      assertTrue(floatingMenu.advancedOpened);
      assertFalse(main.advancedToggleExpanded);
    });
  }

  suite('When in kiosk mode', () => {
    setup(() => {
      loadTimeData.overrideValues({
        isKioskModeActive: true,
      });
    });

    test('Menu is hidden', async () => {
      ui = await createElement();
      const menu = ui.shadowRoot!.querySelector('os-settings-menu');
      assertNull(menu);
    });
  });
});