chromium/chrome/test/data/webui/chromeos/settings/os_people_page/account_manager_subpage_test.ts

// Copyright 2018 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/lazy_load.js';

import {AccountManagerBrowserProxyImpl, SettingsAccountManagerSubpageElement} from 'chrome://os-settings/lazy_load.js';
import {CrIconButtonElement, CrTooltipIconElement, ParentalControlsBrowserProxyImpl, Router, routes, settingMojom, setUserActionRecorderForTesting} from 'chrome://os-settings/os_settings.js';
import {webUIListenerCallback} from 'chrome://resources/js/cr.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
import {getDeepActiveElement} from 'chrome://resources/js/util.js';
import {DomRepeat, 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 {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';

import {FakeUserActionRecorder} from '../fake_user_action_recorder.js';

import {TestAccountManagerBrowserProxy, TestAccountManagerBrowserProxyForUnmanagedAccounts} from './test_account_manager_browser_proxy.js';
import {TestParentalControlsBrowserProxy} from './test_parental_controls_browser_proxy.js';

suite('<settings-account-manager-subpage>', () => {
  let browserProxy: TestAccountManagerBrowserProxy;
  let accountManager: SettingsAccountManagerSubpageElement;
  let accountList: DomRepeat;
  let userActionRecorder: FakeUserActionRecorder;

  suiteSetup(() => {
    loadTimeData.overrideValues({isDeviceAccountManaged: true});

    browserProxy = new TestAccountManagerBrowserProxy();
    AccountManagerBrowserProxyImpl.setInstanceForTesting(browserProxy);
  });

  setup(() => {
    userActionRecorder = new FakeUserActionRecorder();
    setUserActionRecorderForTesting(userActionRecorder);

    accountManager = document.createElement('settings-account-manager-subpage');
    document.body.appendChild(accountManager);
    const list =
        accountManager.shadowRoot!.querySelector<DomRepeat>('#account-list');
    assertTrue(!!list);
    accountList = list;

    Router.getInstance().navigateTo(routes.ACCOUNT_MANAGER);
    flush();
  });

  teardown(() => {
    accountManager.remove();
    browserProxy.reset();
    Router.getInstance().resetRouteForTesting();
  });

  test('AccountListIsPopulatedAtStartup', async () => {
    await browserProxy.whenCalled('getAccounts');
    flush();
    // 1 device account + 3 secondary accounts were added in
    // |getAccounts()| mock above.
    assertEquals(3, accountList.items!.length);
  });

  test('AddAccount', () => {
    const button = accountManager.shadowRoot!.querySelector<HTMLButtonElement>(
        '#add-account-button');
    assertTrue(!!button);
    assertFalse(button.disabled);
    assertNull(accountManager.shadowRoot!.querySelector(
        '.secondary-accounts-disabled-tooltip'));
    button.click();
    assertEquals(1, browserProxy.getCallCount('addAccount'));
  });

  test('ReauthenticateAccount', async () => {
    await browserProxy.whenCalled('getAccounts');
    flush();
    accountManager.shadowRoot!
        .querySelectorAll<HTMLButtonElement>('.reauth-button')[0]!.click();
    assertEquals(1, browserProxy.getCallCount('reauthenticateAccount'));
    const accountEmail = await browserProxy.whenCalled('reauthenticateAccount');
    assertEquals('[email protected]', accountEmail);
  });

  test('UnauthenticatedAccountLabel', async () => {
    await browserProxy.whenCalled('getAccounts');
    flush();
    assertEquals(
        loadTimeData.getString('accountManagerReauthenticationLabel'),
        accountManager.shadowRoot!.querySelectorAll('.reauth-button')[0]!
            .textContent!.trim());
  });

  test('UnmigratedAccountLabel', async () => {
    await browserProxy.whenCalled('getAccounts');
    flush();
    assertEquals(
        loadTimeData.getString('accountManagerMigrationLabel'),
        accountManager.shadowRoot!.querySelectorAll('.reauth-button')[1]!
            .textContent!.trim());
  });

  test('RemoveAccount', async () => {
    await browserProxy.whenCalled('getAccounts');
    flush();
    // Click on 'More Actions' for the second account (First one (index 0)
    // to have the hamburger menu).
    accountManager.shadowRoot!.querySelectorAll('cr-icon-button')[0]!.click();
    // Click on 'Remove account' (the first button in the menu).
    const actionMenu =
        accountManager.shadowRoot!.querySelector('cr-action-menu');
    assertTrue(!!actionMenu);
    actionMenu.querySelectorAll('button')[0]!.click();

    if (loadTimeData.getBoolean('lacrosEnabled')) {
      const confirmationDialog =
          accountManager.shadowRoot!.querySelector('#removeConfirmationDialog');
      assertTrue(!!confirmationDialog);
      const button = confirmationDialog.querySelector<HTMLButtonElement>(
          '#removeConfirmationButton');
      assertTrue(!!button);
      button.click();
    }

    const account = await browserProxy.whenCalled('removeAccount');
    assertEquals('456', account.id);
    // Add account button should be in focus now.
    assertEquals(
        accountManager.shadowRoot!.querySelector('#add-account-button'),
        getDeepActiveElement());
  });

  test('Deep link to remove account button', async () => {
    await browserProxy.whenCalled('getAccounts');
    flush();

    const params = new URLSearchParams();
    params.append('settingId', settingMojom.Setting.kRemoveAccount.toString());
    Router.getInstance().navigateTo(routes.ACCOUNT_MANAGER, params);

    const deepLinkElement =
        accountManager.shadowRoot!.querySelectorAll('cr-icon-button')[0];
    assertTrue(!!deepLinkElement);
    await waitAfterNextRender(deepLinkElement);
    assertEquals(
        deepLinkElement, getDeepActiveElement(),
        'Kebab menu should be focused for settingId=301.');
  });

  test('AccountListIsUpdatedWhenAccountManagerUpdates', () => {
    assertEquals(1, browserProxy.getCallCount('getAccounts'));
    webUIListenerCallback('accounts-changed');
    assertEquals(2, browserProxy.getCallCount('getAccounts'));
  });

  test('ManagementStatusForManagedAccounts', async () => {
    await browserProxy.whenCalled('getAccounts');
    flush();

    const managedBadge = accountManager.shadowRoot!.querySelector<HTMLElement>(
        '.device-account-icon .managed-badge');
    assertTrue(!!managedBadge);
    // Managed badge should be shown for managed accounts.
    assertFalse(managedBadge.hidden);
  });

  test('ArcAvailabilityIsShownForSecondaryAccounts', async () => {
    if (!loadTimeData.getBoolean('arcAccountRestrictionsEnabled')) {
      return;
    }

    await browserProxy.whenCalled('getAccounts');
    flush();

    accountList.items!.forEach((item, i) => {
      const notAvailableInArc =
          accountManager.shadowRoot!.querySelectorAll<HTMLElement>(
              '.arc-availability')[i];
      assertTrue(!!notAvailableInArc);
      assertEquals(item.isAvailableInArc, notAvailableInArc.hidden);
    });
  });

  test('ChangeArcAvailability', async () => {
    if (!loadTimeData.getBoolean('arcAccountRestrictionsEnabled')) {
      return;
    }

    await browserProxy.whenCalled('getAccounts');
    flush();

    const testAccount = accountList.items![0];
    const currentValue = testAccount.isAvailableInArc;
    // Click on 'More Actions' for the |testAccount| (First one (index 0)
    // to have the hamburger menu).
    accountManager.shadowRoot!.querySelectorAll('cr-icon-button')[0]!.click();
    // Click on the button to change ARC availability (the second button in
    // the menu).
    const actionMenu =
        accountManager.shadowRoot!.querySelector('cr-action-menu');
    assertTrue(!!actionMenu);
    actionMenu.querySelectorAll('button')[1]!.click();

    const args = await browserProxy.whenCalled('changeArcAvailability');
    assertEquals(testAccount, args[0]);
    assertEquals(!currentValue, args[1]);
    // 'More actions' button should be in focus now.
    assertEquals(
        accountManager.shadowRoot!.querySelectorAll('cr-icon-button')[0],
        getDeepActiveElement());
  });
});

suite('AccountManagerUnmanagedAccountTests', () => {
  let browserProxy: TestAccountManagerBrowserProxyForUnmanagedAccounts;
  let accountManager: SettingsAccountManagerSubpageElement;

  suiteSetup(() => {
    loadTimeData.overrideValues({isDeviceAccountManaged: false});

    browserProxy = new TestAccountManagerBrowserProxyForUnmanagedAccounts();
    AccountManagerBrowserProxyImpl.setInstanceForTesting(browserProxy);
  });

  setup(() => {
    accountManager = document.createElement('settings-account-manager-subpage');
    document.body.appendChild(accountManager);

    Router.getInstance().navigateTo(routes.ACCOUNT_MANAGER);
  });

  teardown(() => {
    accountManager.remove();
    browserProxy.reset();
    Router.getInstance().resetRouteForTesting();
  });

  test('ManagementStatusForUnmanagedAccounts', async () => {
    await browserProxy.whenCalled('getAccounts');
    flush();

    const managedBadge = accountManager.shadowRoot!.querySelector(
        '.device-account-icon .managed-badge');
    // Managed badge should not be shown for unmanaged accounts.
    assertNull(managedBadge);
  });
});

suite('AccountManagerAccountAdditionDisabledTests', () => {
  let browserProxy: TestAccountManagerBrowserProxy;
  let accountManager: SettingsAccountManagerSubpageElement;

  suiteSetup(() => {
    loadTimeData.overrideValues(
        {secondaryGoogleAccountSigninAllowed: false, isChild: false});

    browserProxy = new TestAccountManagerBrowserProxy();
    AccountManagerBrowserProxyImpl.setInstanceForTesting(browserProxy);
  });

  setup(() => {
    accountManager = document.createElement('settings-account-manager-subpage');
    document.body.appendChild(accountManager);

    Router.getInstance().navigateTo(routes.ACCOUNT_MANAGER);
    flush();
  });

  teardown(() => {
    accountManager.remove();
    browserProxy.reset();
    Router.getInstance().resetRouteForTesting();
  });

  test('AddAccountCanBeDisabledByPolicy', () => {
    const button = accountManager.shadowRoot!.querySelector<HTMLButtonElement>(
        '#add-account-button');
    assertTrue(!!button);
    assertTrue(button.disabled);
    assertTrue(!!accountManager.shadowRoot!.querySelector(
        '.secondary-accounts-disabled-tooltip'));
  });

  test('UserMessageSetForAccountType', () => {
    const tooltip =
        accountManager.shadowRoot!.querySelector<CrTooltipIconElement>(
            '.secondary-accounts-disabled-tooltip');
    assertTrue(!!tooltip);
    assertEquals(
        loadTimeData.getString('accountManagerSecondaryAccountsDisabledText'),
        tooltip.tooltipText);
  });
});

suite('AccountManagerAccountAdditionDisabledChildAccountTests', () => {
  let browserProxy: TestAccountManagerBrowserProxy;
  let accountManager: SettingsAccountManagerSubpageElement;

  suiteSetup(() => {
    loadTimeData.overrideValues(
        {secondaryGoogleAccountSigninAllowed: false, isChild: true});

    browserProxy = new TestAccountManagerBrowserProxy();
    AccountManagerBrowserProxyImpl.setInstanceForTesting(browserProxy);
  });

  setup(() => {
    accountManager = document.createElement('settings-account-manager-subpage');
    document.body.appendChild(accountManager);

    Router.getInstance().navigateTo(routes.ACCOUNT_MANAGER);
    flush();
  });

  teardown(() => {
    accountManager.remove();
    browserProxy.reset();
    Router.getInstance().resetRouteForTesting();
  });

  test('UserMessageSetForAccountType', () => {
    const tooltip =
        accountManager.shadowRoot!.querySelector<CrTooltipIconElement>(
            '.secondary-accounts-disabled-tooltip');
    assertTrue(!!tooltip);
    assertEquals(
        loadTimeData.getString(
            'accountManagerSecondaryAccountsDisabledChildText'),
        tooltip.tooltipText);
  });
});

suite('AccountManagerAccountChildAccountTests', () => {
  let parentalControlsBrowserProxy: TestParentalControlsBrowserProxy;
  let accountManager: SettingsAccountManagerSubpageElement;

  suiteSetup(() => {
    loadTimeData.overrideValues({isChild: true, isDeviceAccountManaged: true});

    parentalControlsBrowserProxy = new TestParentalControlsBrowserProxy();
    ParentalControlsBrowserProxyImpl.setInstanceForTesting(
        parentalControlsBrowserProxy);
  });

  setup(() => {
    accountManager = document.createElement('settings-account-manager-subpage');
    document.body.appendChild(accountManager);

    Router.getInstance().navigateTo(routes.ACCOUNT_MANAGER);
    flush();
  });

  teardown(() => {
    accountManager.remove();
    parentalControlsBrowserProxy.reset();
    Router.getInstance().resetRouteForTesting();
  });

  test('FamilyLinkIcon', () => {
    const icon = accountManager.shadowRoot!.querySelector<CrIconButtonElement>(
        '.managed-message cr-icon-button');
    assertTrue(!!icon, 'Could not find the managed icon');

    assertEquals('cr20:kite', icon.ironIcon);

    icon.click();
    assertEquals(
        1,
        parentalControlsBrowserProxy.getCallCount('launchFamilyLinkSettings'));
  });
});