chromium/chrome/test/data/webui/settings/sync_account_control_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://settings/settings.js';

import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import type {CrActionMenuElement, SettingsSyncAccountControlElement, StoredAccount} from 'chrome://settings/settings.js';
import {MAX_SIGNIN_PROMO_IMPRESSION, Router, SignedInState, StatusAction, SyncBrowserProxyImpl} from 'chrome://settings/settings.js';
import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {isChildVisible, isVisible} from 'chrome://webui-test/test_util.js';

import {simulateStoredAccounts} from './sync_test_util.js';
import {TestSyncBrowserProxy} from './test_sync_browser_proxy.js';


suite('SyncAccountControl', function() {
  let browserProxy: TestSyncBrowserProxy;
  let testElement: SettingsSyncAccountControlElement;

  function forcePromoResetWithCount(count: number, syncing: boolean) {
    browserProxy.setImpressionCount(count);
    // Flipping syncStatus.signedInState will force promo state to be reset.
    const opposite_syncing =
        syncing ? SignedInState.SIGNED_OUT : SignedInState.SYNCING;
    const sync_state =
        syncing ? SignedInState.SYNCING : SignedInState.SIGNED_OUT;
    testElement.syncStatus = {
      signedInState: opposite_syncing,
      statusAction: StatusAction.NO_ACTION,
    };
    testElement.syncStatus = {
      signedInState: sync_state,
      statusAction: StatusAction.NO_ACTION,
    };
  }

  setup(async function() {
    browserProxy = new TestSyncBrowserProxy();
    SyncBrowserProxyImpl.setInstance(browserProxy);

    document.body.innerHTML = window.trustedTypes!.emptyHTML;
    testElement = document.createElement('settings-sync-account-control');
    testElement.syncStatus = {
      signedInState: SignedInState.SYNCING,
      signedInUsername: '[email protected]',
      statusAction: StatusAction.NO_ACTION,
    };
    testElement.prefs = {
      signin: {
        allowed_on_next_startup:
            {type: chrome.settingsPrivate.PrefType.BOOLEAN, value: true},
      },
    };

    document.body.appendChild(testElement);

    await browserProxy.whenCalled('getStoredAccounts');
    flush();
    simulateStoredAccounts([
      {
        fullName: 'fooName',
        givenName: 'foo',
        email: '[email protected]',
      },
      {
        fullName: 'barName',
        givenName: 'bar',
        email: '[email protected]',
      },
    ]);
  });

  teardown(function() {
    testElement.remove();
  });

  test('promo shows/hides in the right states', async function() {
    // Not signed in, no accounts, will show banner.
    simulateStoredAccounts([]);
    forcePromoResetWithCount(0, false);
    const banner = testElement.shadowRoot!.querySelector('#banner');
    assertTrue(isVisible(banner));
    // Changing `signedInState` in forcePromoResetWithCount should increment
    // count.
    await browserProxy.whenCalled('incrementPromoImpressionCount');
    forcePromoResetWithCount(MAX_SIGNIN_PROMO_IMPRESSION + 1, false);
    assertFalse(isVisible(banner));

    // Not signed in, has accounts, will show banner.
    simulateStoredAccounts([{email: '[email protected]'}]);
    forcePromoResetWithCount(0, false);
    assertTrue(isVisible(banner));
    forcePromoResetWithCount(MAX_SIGNIN_PROMO_IMPRESSION + 1, false);
    assertFalse(isVisible(banner));

    // signed in, banners never show.
    simulateStoredAccounts([{email: '[email protected]'}]);
    forcePromoResetWithCount(0, true);
    assertFalse(isVisible(banner));
    forcePromoResetWithCount(MAX_SIGNIN_PROMO_IMPRESSION + 1, true);
    assertFalse(isVisible(banner));
  });

  test('promo header is visible', function() {
    testElement.syncStatus = {
      signedInState: SignedInState.SIGNED_OUT,
      signedInUsername: '',
      statusAction: StatusAction.NO_ACTION,
    };
    testElement.promoLabelWithNoAccount = testElement.promoLabelWithAccount =
        'title';
    simulateStoredAccounts([]);
    assertTrue(isChildVisible(testElement, '#promo-header'));
  });

  test('not signed in and no stored accounts', function() {
    testElement.syncStatus = {
      signedInState: SignedInState.SIGNED_OUT,
      signedInUsername: '',
      statusAction: StatusAction.NO_ACTION,
    };
    simulateStoredAccounts([]);

    assertTrue(isChildVisible(testElement, '#promo-header'));
    assertFalse(isChildVisible(testElement, '#avatar-row'));

    // Chrome OS does not use the account switch menu.
    assertFalse(isChildVisible(testElement, '#menu'));

    assertTrue(isChildVisible(testElement, '#signIn'));

    testElement.$.signIn.click();

    return browserProxy.whenCalled('startSignIn');
  });

  test('not signed in but has stored accounts', async function() {
    loadTimeData.overrideValues({isSecondaryUser: true});
    testElement.syncStatus = {
      firstSetupInProgress: false,
      signedInState: SignedInState.SIGNED_OUT,
      signedInUsername: '',
      statusAction: StatusAction.NO_ACTION,
      hasError: false,
      disabled: false,
    };
    simulateStoredAccounts([
      {
        fullName: 'fooName',
        givenName: 'foo',
        email: '[email protected]',
      },
      {
        fullName: 'barName',
        givenName: 'bar',
        email: '[email protected]',
      },
    ]);

    const userInfo =
        testElement.shadowRoot!.querySelector<HTMLElement>('#user-info')!;
    const syncButton =
        testElement.shadowRoot!.querySelector<HTMLElement>('#sync-button')!;

    // Avatar row shows the right account.
    assertTrue(isChildVisible(testElement, '#promo-header'));
    assertTrue(isChildVisible(testElement, '#avatar-row'));
    assertTrue(userInfo.textContent!.includes('fooName'));
    assertTrue(userInfo.textContent!.includes('[email protected]'));
    assertFalse(userInfo.textContent!.includes('barName'));
    assertFalse(userInfo.textContent!.includes('[email protected]'));

    // Menu contains the right items.
    assertTrue(!!testElement.shadowRoot!.querySelector('#menu'));
    assertFalse(
        testElement.shadowRoot!.querySelector<CrActionMenuElement>(
                                   '#menu')!.open);
    const items =
        testElement.shadowRoot!.querySelectorAll<HTMLElement>('.dropdown-item');
    assertEquals(4, items.length);
    assertTrue(items[0]!.textContent!.includes('[email protected]'));
    assertTrue(items[1]!.textContent!.includes('[email protected]'));
    assertEquals(items[2]!.id, 'sign-in-item');
    assertEquals(items[3]!.id, 'sign-out-item');

    // "sync to" button is showing the correct name and syncs with the
    // correct account when clicked.
    assertTrue(isVisible(syncButton));
    assertFalse(isChildVisible(testElement, '#turn-off'));
    syncButton.click();
    flush();

    let [email, isDefaultPromoAccount] =
        await browserProxy.whenCalled('startSyncingWithEmail');
    assertEquals(email, '[email protected]');
    assertEquals(isDefaultPromoAccount, true);

    assertTrue(isChildVisible(testElement, 'cr-icon-button'));
    assertTrue(testElement.shadowRoot!
                   .querySelector<HTMLElement>('#sync-icon-container')!.hidden);

    assertTrue(isChildVisible(testElement, '#dropdown-arrow'));
    testElement.shadowRoot!.querySelector<HTMLElement>(
                               '#dropdown-arrow')!.click();
    flush();
    assertTrue(
        testElement.shadowRoot!.querySelector<CrActionMenuElement>(
                                   '#menu')!.open);

    // Switching selected account will update UI with the right name and
    // email.
    items[1]!.click();
    flush();
    assertFalse(userInfo.textContent!.includes('fooName'));
    assertFalse(userInfo.textContent!.includes('[email protected]'));
    assertTrue(userInfo.textContent!.includes('barName'));
    assertTrue(userInfo.textContent!.includes('[email protected]'));
    assertTrue(isVisible(syncButton));

    browserProxy.resetResolver('startSyncingWithEmail');
    syncButton.click();
    flush();

    [email, isDefaultPromoAccount] =
        await browserProxy.whenCalled('startSyncingWithEmail');
    assertEquals(email, '[email protected]');
    assertEquals(isDefaultPromoAccount, false);

    // Tapping the last menu item will initiate sign-in.
    items[2]!.click();
    await browserProxy.whenCalled('startSignIn');
  });

  test('managedUser, Sync off, turn sync off disabled', function() {
    loadTimeData.overrideValues({turnOffSyncAllowedForManagedProfiles: false});

    testElement.syncStatus = {
      signedInState: SignedInState.SIGNED_IN,
      disabled: false,
      hasError: false,
      domain: 'domain',
      statusAction: StatusAction.NO_ACTION,
    };
    flush();
    assertTrue(isChildVisible(testElement, '#sync-button'));
    assertTrue(!!testElement.shadowRoot!.querySelector('#menu'));
    assertTrue(isChildVisible(testElement, '#dropdown-arrow'));
  });

  test('managedUser, Sync off, turn sync off enabled', function() {
    loadTimeData.overrideValues({turnOffSyncAllowedForManagedProfiles: true});

    testElement.syncStatus = {
      signedInState: SignedInState.SIGNED_IN,
      disabled: false,
      hasError: false,
      domain: 'domain',
      statusAction: StatusAction.NO_ACTION,
    };
    flush();
    assertTrue(isChildVisible(testElement, '#sync-button'));
    // Menu is hidden.
    assertFalse(!!testElement.shadowRoot!.querySelector('#menu'));
    assertFalse(isChildVisible(testElement, '#dropdown-arrow'));
  });

  // <if expr="chromeos_lacros">
  test('main profile not signed in but has stored accounts', function() {
    loadTimeData.overrideValues({isSecondaryUser: false});
    testElement.syncStatus = {
      firstSetupInProgress: false,
      signedInState: SignedInState.SIGNED_OUT,
      signedInUsername: '',
      statusAction: StatusAction.NO_ACTION,
      hasError: false,
      disabled: false,
    };
    simulateStoredAccounts([
      {
        fullName: 'fooName',
        givenName: 'foo',
        email: '[email protected]',
      },
    ]);

    const userInfo =
        testElement.shadowRoot!.querySelector<HTMLElement>('#user-info')!;

    // Avatar row shows the right account.
    assertTrue(isChildVisible(testElement, '#promo-header'));
    assertTrue(isChildVisible(testElement, '#avatar-row'));
    assertTrue(userInfo.textContent!.includes('fooName'));
    assertTrue(userInfo.textContent!.includes('[email protected]'));

    // Menu is hidden.
    assertFalse(!!testElement.shadowRoot!.querySelector('#menu'));
    assertFalse(isChildVisible(testElement, '#dropdown-arrow'));
  });
  // </if>

  test('signed in, no error', function() {
    testElement.syncStatus = {
      firstSetupInProgress: false,
      signedInState: SignedInState.SYNCING,
      signedInUsername: '[email protected]',
      statusAction: StatusAction.NO_ACTION,
      hasError: false,
      hasUnrecoverableError: false,
      disabled: false,
    };
    flush();

    assertTrue(isChildVisible(testElement, '#avatar-row'));
    assertFalse(isChildVisible(testElement, '#promo-header'));
    assertFalse(
        testElement.shadowRoot!
            .querySelector<HTMLElement>('#sync-icon-container')!.hidden);

    assertFalse(isChildVisible(testElement, 'cr-icon-button'));
    assertFalse(!!testElement.shadowRoot!.querySelector('#menu'));
    assertFalse(isChildVisible(testElement, '#dropdown-arrow'));

    const userInfo =
        testElement.shadowRoot!.querySelector<HTMLElement>('#user-info')!;
    assertTrue(userInfo.textContent!.includes('barName'));
    assertTrue(userInfo.textContent!.includes('[email protected]'));
    assertFalse(userInfo.textContent!.includes('fooName'));
    assertFalse(userInfo.textContent!.includes('[email protected]'));

    assertFalse(isChildVisible(testElement, '#sync-button'));
    assertTrue(isChildVisible(testElement, '#turn-off'));
    assertFalse(isChildVisible(testElement, '#sync-error-button'));

    testElement.shadowRoot!.querySelector<HTMLElement>(
                               '#avatar-row #turn-off')!.click();
    flush();

    assertEquals(
        Router.getInstance().getCurrentRoute(),
        Router.getInstance().getRoutes().SIGN_OUT);
  });

  test('signed in, has error', function() {
    testElement.syncStatus = {
      firstSetupInProgress: false,
      signedInState: SignedInState.SYNCING,
      signedInUsername: '[email protected]',
      hasError: true,
      hasUnrecoverableError: false,
      statusAction: StatusAction.CONFIRM_SYNC_SETTINGS,
      disabled: false,
    };
    flush();
    const userInfo = testElement.shadowRoot!.querySelector('#user-info')!;

    assertTrue(
        testElement.shadowRoot!
            .querySelector<HTMLElement>(
                '#sync-icon-container')!.classList.contains('sync-problem'));
    assertTrue(!!testElement.shadowRoot!.querySelector(
        '[icon="settings:sync-problem"]'));
    let displayedText =
        userInfo.querySelector<HTMLElement>('div:not([hidden])')!.textContent!;
    assertFalse(displayedText.includes('barName'));
    assertFalse(displayedText.includes('fooName'));
    assertTrue(displayedText.includes('Sync isn\'t working'));
    // The sync error button is shown to resolve the error.
    assertTrue(isChildVisible(testElement, '#sync-error-button'));

    testElement.syncStatus = {
      firstSetupInProgress: false,
      signedInState: SignedInState.SYNCING,
      signedInUsername: '[email protected]',
      hasError: true,
      hasUnrecoverableError: false,
      statusAction: StatusAction.REAUTHENTICATE,
      disabled: false,
    };
    assertTrue(
        testElement.shadowRoot!
            .querySelector<HTMLElement>(
                '#sync-icon-container')!.classList.contains('sync-paused'));
    assertTrue(!!testElement.shadowRoot!.querySelector(
        '[icon=\'settings:sync-disabled\']'));
    displayedText =
        userInfo.querySelector<HTMLElement>('div:not([hidden])')!.textContent!;
    assertFalse(displayedText.includes('barName'));
    assertFalse(displayedText.includes('fooName'));
    assertTrue(displayedText.includes('Sync is paused'));
    // The sync error button is shown to resolve the error.
    assertTrue(isChildVisible(testElement, '#sync-error-button'));

    testElement.syncStatus = {
      firstSetupInProgress: false,
      signedInState: SignedInState.SYNCING,
      signedInUsername: '[email protected]',
      statusAction: StatusAction.NO_ACTION,
      hasError: false,
      hasUnrecoverableError: false,
      disabled: true,
    };

    assertTrue(
        testElement.shadowRoot!
            .querySelector<HTMLElement>(
                '#sync-icon-container')!.classList.contains('sync-disabled'));
    assertTrue(!!testElement.shadowRoot!.querySelector('[icon=\'cr:sync\']'));
    displayedText =
        userInfo.querySelector<HTMLElement>('div:not([hidden])')!.textContent!;
    assertFalse(displayedText.includes('barName'));
    assertFalse(displayedText.includes('fooName'));
    assertTrue(displayedText.includes('Sync disabled'));
    assertFalse(isChildVisible(testElement, '#sync-error-button'));

    testElement.syncStatus = {
      firstSetupInProgress: false,
      signedInState: SignedInState.SYNCING,
      signedInUsername: '[email protected]',
      statusAction: StatusAction.REAUTHENTICATE,
      hasError: true,
      hasUnrecoverableError: true,
      disabled: false,
    };
    assertTrue(
        testElement.shadowRoot!
            .querySelector<HTMLElement>(
                '#sync-icon-container')!.classList.contains('sync-problem'));
    assertTrue(!!testElement.shadowRoot!.querySelector(
        '[icon="settings:sync-problem"]'));
    displayedText =
        userInfo.querySelector<HTMLElement>('div:not([hidden])')!.textContent!;
    assertFalse(displayedText.includes('barName'));
    assertFalse(displayedText.includes('fooName'));
    assertTrue(displayedText.includes('Sync isn\'t working'));

    testElement.syncStatus = {
      firstSetupInProgress: false,
      signedInState: SignedInState.SYNCING,
      signedInUsername: '[email protected]',
      statusAction: StatusAction.RETRIEVE_TRUSTED_VAULT_KEYS,
      hasError: true,
      hasPasswordsOnlyError: true,
      hasUnrecoverableError: false,
      disabled: false,
    };
    assertTrue(
        testElement.shadowRoot!
            .querySelector<HTMLElement>(
                '#sync-icon-container')!.classList.contains('sync-problem'));
    assertTrue(!!testElement.shadowRoot!.querySelector(
        '[icon="settings:sync-problem"]'));
    displayedText =
        userInfo.querySelector<HTMLElement>('div:not([hidden])')!.textContent!;
    assertFalse(displayedText.includes('barName'));
    assertFalse(displayedText.includes('fooName'));
    assertFalse(displayedText.includes('Sync isn\'t working'));
    assertTrue(displayedText.includes('Password sync isn\'t working'));
    // The sync error button is shown to resolve the error.
    assertTrue(isChildVisible(testElement, '#sync-error-button'));
    assertTrue(isChildVisible(testElement, '#turn-off'));
  });

  test('signed in, setup in progress', function() {
    testElement.syncStatus = {
      signedInState: SignedInState.SYNCING,
      signedInUsername: '[email protected]',
      statusAction: StatusAction.NO_ACTION,
      statusText: 'Setup in progress...',
      firstSetupInProgress: true,
      hasError: false,
      hasUnrecoverableError: false,
      disabled: false,
    };
    flush();
    const userInfo = testElement.shadowRoot!.querySelector('#user-info')!;
    const setupButtons =
        testElement.shadowRoot!.querySelector('#setup-buttons');

    assertTrue(userInfo.textContent!.includes('barName'));
    assertTrue(userInfo.textContent!.includes('Setup in progress...'));
    assertTrue(isVisible(setupButtons));
  });

  test('embedded in another page', function() {
    testElement.embeddedInSubpage = true;
    forcePromoResetWithCount(100, false);
    const banner = testElement.shadowRoot!.querySelector('#banner');
    assertTrue(isVisible(banner));

    testElement.syncStatus = {
      firstSetupInProgress: false,
      signedInState: SignedInState.SYNCING,
      signedInUsername: '[email protected]',
      statusAction: StatusAction.NO_ACTION,
      hasError: false,
      hasUnrecoverableError: false,
      disabled: false,
    };

    assertTrue(isChildVisible(testElement, '#turn-off'));
    assertFalse(isChildVisible(testElement, '#sync-error-button'));

    testElement.embeddedInSubpage = true;
    testElement.syncStatus = {
      firstSetupInProgress: false,
      signedInState: SignedInState.SYNCING,
      signedInUsername: '[email protected]',
      hasError: true,
      hasUnrecoverableError: false,
      statusAction: StatusAction.REAUTHENTICATE,
      disabled: false,
    };
    assertTrue(isChildVisible(testElement, '#turn-off'));
    assertTrue(isChildVisible(testElement, '#sync-error-button'));

    testElement.embeddedInSubpage = true;
    testElement.syncStatus = {
      firstSetupInProgress: false,
      signedInState: SignedInState.SYNCING,
      signedInUsername: '[email protected]',
      hasError: true,
      hasUnrecoverableError: true,
      statusAction: StatusAction.REAUTHENTICATE,
      disabled: false,
    };
    assertTrue(isChildVisible(testElement, '#turn-off'));
    assertTrue(isChildVisible(testElement, '#sync-error-button'));

    testElement.embeddedInSubpage = true;
    testElement.syncStatus = {
      firstSetupInProgress: false,
      signedInState: SignedInState.SYNCING,
      signedInUsername: '[email protected]',
      hasError: true,
      hasUnrecoverableError: false,
      statusAction: StatusAction.ENTER_PASSPHRASE,
      disabled: false,
    };
    assertTrue(isChildVisible(testElement, '#turn-off'));
    // Don't show passphrase error button on embedded page.
    assertFalse(isChildVisible(testElement, '#sync-error-button'));

    testElement.embeddedInSubpage = true;
    testElement.syncStatus = {
      firstSetupInProgress: false,
      signedInState: SignedInState.SYNCING,
      signedInUsername: '[email protected]',
      hasError: true,
      hasUnrecoverableError: true,
      statusAction: StatusAction.NO_ACTION,
      disabled: false,
    };
    assertTrue(isChildVisible(testElement, '#turn-off'));
    assertFalse(isChildVisible(testElement, '#sync-error-button'));
  });

  test('hide buttons', function() {
    testElement.hideButtons = true;
    testElement.syncStatus = {
      firstSetupInProgress: false,
      signedInState: SignedInState.SYNCING,
      signedInUsername: '[email protected]',
      statusAction: StatusAction.NO_ACTION,
      hasError: false,
      hasUnrecoverableError: false,
      disabled: false,
    };

    assertFalse(isChildVisible(testElement, '#turn-off'));
    assertFalse(isChildVisible(testElement, '#sync-error-button'));

    testElement.syncStatus = {
      firstSetupInProgress: false,
      signedInState: SignedInState.SYNCING,
      signedInUsername: '[email protected]',
      hasError: true,
      hasUnrecoverableError: false,
      statusAction: StatusAction.REAUTHENTICATE,
      disabled: false,
    };
    assertFalse(isChildVisible(testElement, '#turn-off'));
    assertFalse(isChildVisible(testElement, '#sync-error-button'));

    testElement.syncStatus = {
      firstSetupInProgress: false,
      signedInState: SignedInState.SYNCING,
      signedInUsername: '[email protected]',
      hasError: true,
      hasUnrecoverableError: false,
      statusAction: StatusAction.ENTER_PASSPHRASE,
      disabled: false,
    };
    assertFalse(isChildVisible(testElement, '#turn-off'));
    assertFalse(isChildVisible(testElement, '#sync-error-button'));
  });

  test('signinButtonDisabled', function() {
    // Ensure that the sync button is disabled when signin is disabled.
    assertFalse(testElement.$.signIn.disabled);
    testElement.setPrefValue('signin.allowed_on_next_startup', false);
    flush();
    assertTrue(testElement.$.signIn.disabled);
  });

  test('signinPaused effects', function() {
    // <if expr="chromeos_lacros">
    // For Lacros, force the page to be loaded as if it was a secondary user so
    // that it is similar to other platforms. E.g. the drowdown menu would not
    // show on lacros main user.
    loadTimeData.overrideValues({isSecondaryUser: true});
    // </if>

    const signedInAccount: StoredAccount = {
      fullName: 'fooName',
      givenName: 'foo',
      email: '[email protected]',
      isPrimaryAccount: true,
    };
    // Set primary account.
    simulateStoredAccounts([signedInAccount]);

    // Signed in but not syncing.
    testElement.syncStatus = {
      statusAction: StatusAction.NO_ACTION,
      signedInState: SignedInState.SIGNED_IN,
    };

    assertTrue(isChildVisible(testElement, '#avatar-row'));
    const userInfo =
        testElement.shadowRoot!.querySelector<HTMLElement>('#user-info')!;
    const secondaryContentSignedIn = userInfo.children[1]!.textContent!;
    assertNotEquals(secondaryContentSignedIn.trim(), signedInAccount.email);
    assertFalse(isChildVisible(testElement, '#signin-paused-buttons'));
    assertTrue(isChildVisible(testElement, '#dropdown-arrow'));
    assertTrue(isChildVisible(testElement, '#sync-button'));

    // Set Signed in Paused state.
    testElement.syncStatus = {
      statusAction: StatusAction.NO_ACTION,
      signedInState: SignedInState.SIGNED_IN_PAUSED,
    };

    assertTrue(isChildVisible(testElement, '#avatar-row'));
    const secondaryContentSigninPaused = userInfo.children[1]!.textContent!;
    assertNotEquals(secondaryContentSignedIn, secondaryContentSigninPaused);
    assertEquals(secondaryContentSigninPaused.trim(), signedInAccount.email);
    assertTrue(isChildVisible(testElement, '#signin-paused-buttons'));
    assertFalse(isChildVisible(testElement, '#dropdown-arrow'));
    assertFalse(isChildVisible(testElement, '#sync-button'));
  });

  test('webOnlySignedIn effects', function() {
    const signedInAccount: StoredAccount = {
      fullName: 'fooName',
      givenName: 'foo',
      email: '[email protected]',
      isPrimaryAccount: true,
    };
    // Set primary account.
    simulateStoredAccounts([signedInAccount]);

    // Signed in but not syncing.
    testElement.syncStatus = {
      statusAction: StatusAction.NO_ACTION,
      signedInState: SignedInState.SIGNED_IN,
    };

    assertTrue(isChildVisible(testElement, '#avatar-row'));

    // Set WebOnlySignedIn.
    testElement.syncStatus = {
      statusAction: StatusAction.NO_ACTION,
      signedInState: SignedInState.WEB_ONLY_SIGNED_IN,
    };
    simulateStoredAccounts([signedInAccount]);

    assertFalse(isChildVisible(testElement, '#avatar-row'));
  });
});