chromium/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/integration_test.js

// 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://multidevice-setup/strings.m.js';
import 'chrome://resources/ash/common/multidevice_setup/multidevice_setup.js';

import {FakeMojoService} from 'chrome://resources/ash/common/multidevice_setup/fake_mojo_service.js';
import {BrowserProxyImpl} from 'chrome://resources/ash/common/multidevice_setup/multidevice_setup_browser_proxy.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 {waitBeforeNextRender} from 'chrome://webui-test/polymer_test_util.js';

import {FakeQuickUnlockPrivate} from '../../../chromeos/settings/fake_quick_unlock_private.js';
import {eventToPromise} from '../../../test_util.js';

import {TestMultideviceSetupBrowserProxy} from './setup_succeeded_page_test.js';



/** @fileoverview Suite of integration tests for MultiDevice setup WebUI. */
/** @implements {multidevice_setup.MultiDeviceSetupDelegate} */
class FakeDelegate {
  constructor() {
    /** @private {boolean} */
    this.isPasswordRequiredToSetHost_ = true;

    /** @private {boolean} */
    this.shouldSetHostSucceed_ = true;

    this.numSetHostDeviceCalls = 0;
  }

  set isPasswordRequired(isPasswordRequired) {
    this.isPasswordRequiredToSetHost_ = isPasswordRequired;
  }

  /** @override */
  isPasswordRequiredToSetHost() {
    return this.isPasswordRequiredToSetHost_;
  }

  set shouldSetHostSucceed(shouldSetHostSucceed) {
    this.shouldSetHostSucceed_ = shouldSetHostSucceed;
  }

  /** @override */
  setHostDevice(hostInstanceIdOrLegacyDeviceId, opt_authToken) {
    return new Promise((resolve) => {
      this.numSetHostDeviceCalls++;
      resolve({success: this.shouldSetHostSucceed_});
    });
  }

  set shouldExitSetupFlowAfterHostSet(shouldExitSetupFlowAfterHostSet) {
    this.shouldExitSetupFlowAfterSettingHost_ = shouldExitSetupFlowAfterHostSet;
  }

  /** @override */
  shouldExitSetupFlowAfterSettingHost() {
    return this.shouldExitSetupFlowAfterSettingHost_;
  }

  /** @override */
  getStartSetupCancelButtonTextId() {
    return 'cancel';
  }
}

/** @implements {multidevice_setup.MojoInterfaceProvider} */
class FakeMojoInterfaceProviderImpl {
  /** @param {!FakeMojoService} fakeMojoService */
  constructor(fakeMojoService) {
    /** @private {!FakeMojoService} */
    this.fakeMojoService_ = fakeMojoService;
  }

  /** @override */
  getInterfacePtr() {
    return this.fakeMojoService_;
  }
}

suite('MultiDeviceSetup', () => {
  /**
   * MultiDeviceSetup created before each test. Defined in setUp.
   * @type {MultiDeviceSetup|undefined}
   */
  let multiDeviceSetupElement;

  /**
   * Forward navigation button. Defined in setUp.
   * @type {PaperButton|undefined}
   */
  let forwardButton;

  /**
   * Cancel button. Defined in setUp.
   * @type {PaperButton|undefined}
   */
  let cancelButton;

  /**
   * Backward navigation button. Defined in setUp.
   * @type {PaperButton|undefined}
   */
  let backwardButton;

  /** @type {!FakeMojoService} */
  let fakeMojoService;

  /** @type {!FakeQuickUnlockPrivate} */
  let fakeQuickUnlockPrivate;

  /** @type {?TestMultideviceSetupBrowserProxy} */
  let browserProxy = null;

  const PASSWORD = 'password-page';
  const SUCCESS = 'setup-succeeded-page';
  const START = 'start-setup-page';

  const CORRECT_PASSWORD = 'correctPassword';
  const WRONG_PASSWORD = 'wrongPassword';

  setup(async () => {
    browserProxy = new TestMultideviceSetupBrowserProxy();
    BrowserProxyImpl.setInstance(browserProxy);

    multiDeviceSetupElement = document.createElement('multidevice-setup');
    multiDeviceSetupElement.delegate = new FakeDelegate();
    fakeMojoService = new FakeMojoService();
    multiDeviceSetupElement.mojoInterfaceProvider_ =
        new FakeMojoInterfaceProviderImpl(fakeMojoService);

    document.body.appendChild(multiDeviceSetupElement);
    flush();

    forwardButton = multiDeviceSetupElement.$$('button-bar').$$('#forward');
    cancelButton = multiDeviceSetupElement.$$('button-bar').$$('#cancel');
    backwardButton = multiDeviceSetupElement.$$('button-bar').$$('#backward');

    fakeQuickUnlockPrivate = new FakeQuickUnlockPrivate();
    fakeQuickUnlockPrivate.accountPassword = CORRECT_PASSWORD;
    multiDeviceSetupElement.$$(PASSWORD).quickUnlockPrivate_ =
        fakeQuickUnlockPrivate;
  });

  /** @param {boolean} isOobeMode */
  function setMode(isOobeMode) {
    multiDeviceSetupElement.delegate.isPasswordRequired = !isOobeMode;
    multiDeviceSetupElement.delegate.shouldExitSetupFlowAfterHostSet =
        isOobeMode;
  }

  /**
   * @param {string} visiblePageName
   * @return {!Promise} Promise that resolves when the page renders.
   */
  function setVisiblePage(visiblePageName) {
    multiDeviceSetupElement.visiblePageName = visiblePageName;
    flush();
    return waitBeforeNextRender(multiDeviceSetupElement.$$(visiblePageName));
  }

  /**
   * @param {string} input
   * @return {!Promise} Promise that resolves when the page renders.
   */
  function enterPassword(input) {
    multiDeviceSetupElement.$$(PASSWORD).$$('#passwordInput').value = input;
    flush();
    return waitBeforeNextRender(multiDeviceSetupElement);
  }

  function getNumSetHostDeviceCalls() {
    return multiDeviceSetupElement.delegate.numSetHostDeviceCalls;
  }

  // *** From SetupSucceededPage ***

  test('SetupSucceededPage buttons: forward', () => {
    return setVisiblePage(SUCCESS).then(() => {
      assertFalse(forwardButton.hidden);
      assertTrue(cancelButton.hidden);
      assertTrue(backwardButton.hidden);
    });
  });

  test('SetupSucceededPage forward button closes UI', () => {
    return setVisiblePage(SUCCESS).then(() => {
      const whenSetupExits =
          eventToPromise('setup-exited', multiDeviceSetupElement);
      forwardButton.click();
      return whenSetupExits;
    });
  });

  // Post-OOBE

  test('SetupSucceededPage Settings link closes UI (post-OOBE)', () => {
    setMode(false /* isOobeMode */);
    return setVisiblePage(SUCCESS).then(() => {
      const whenSetupExits =
          eventToPromise('setup-exited', multiDeviceSetupElement);
      multiDeviceSetupElement.$$(SUCCESS).$$('#settings-link').click();
      return whenSetupExits;
    });
  });

  // *** From StartSetupPage ***

  test('StartSetupPage buttons: forward, cancel', () => {
    return setVisiblePage(START).then(() => {
      assertFalse(forwardButton.hidden);
      assertFalse(cancelButton.hidden);
      assertTrue(backwardButton.hidden);
    });
  });

  // OOBE

  test('StartSetupPage cancel button exits OOBE (OOBE)', () => {
    setMode(true /* isOobeMode */);

    return setVisiblePage(START)
        .then(() => {
          const whenSetupExits =
              eventToPromise('setup-exited', multiDeviceSetupElement);
          cancelButton.click();
          return whenSetupExits;
        })
        .then(() => {
          assertEquals(0, getNumSetHostDeviceCalls());
        });
  });

  test(
      'StartSetupPage forward button sets host in background and ' +
          'exits OOBE (OOBE)',
      () => {
        setMode(true /* isOobeMode */);

        return setVisiblePage(START)
            .then(() => {
              multiDeviceSetupElement.delegate.shouldSetHostSucceed = true;
              const whenSetupExits =
                  eventToPromise('setup-exited', multiDeviceSetupElement);
              forwardButton.click();
              return whenSetupExits;
            })
            .then(() => {
              assertEquals(1, getNumSetHostDeviceCalls());
            });
      });

  // Post-OOBE

  test('StartSetupPage cancel button closes UI (post-OOBE)', () => {
    setMode(false /* isOobeMode */);

    return setVisiblePage(START)
        .then(() => {
          const whenSetupExits =
              eventToPromise('setup-exited', multiDeviceSetupElement);
          cancelButton.click();
          return whenSetupExits;
        })
        .then(() => {
          assertEquals(0, getNumSetHostDeviceCalls());
        });
  });

  // *** From PasswordPage ***

  // Post-OOBE

  test('PasswordPage buttons: forward, cancel, backward (post-OOBE)', () => {
    return setVisiblePage(PASSWORD).then(() => {
      assertFalse(forwardButton.hidden);
      assertFalse(cancelButton.hidden);
      assertFalse(backwardButton.hidden);
    });
  });

  test('PasswordPage cancel button closes UI (post-OOBE)', () => {
    setMode(false /* isOobeMode */);

    return setVisiblePage(PASSWORD)
        .then(() => {
          const whenSetupExits =
              eventToPromise('setup-exited', multiDeviceSetupElement);
          cancelButton.click();
          return whenSetupExits;
        })
        .then(() => {
          assertEquals(0, getNumSetHostDeviceCalls());
        });
  });

  test('PasswordPage backward button goes to start page (post-OOBE)', () => {
    setMode(false /* isOobeMode */);

    return setVisiblePage(PASSWORD)
        .then(() => {
          const whenPageChanges = eventToPromise(
              'visible-page-name-changed', multiDeviceSetupElement);
          backwardButton.click();
          return whenPageChanges;
        })
        .then(() => {
          assertEquals(START, multiDeviceSetupElement.visiblePageName);
          assertEquals(0, getNumSetHostDeviceCalls());
        });
  });

  test(
      'PasswordPage forward button goes to success page if mojo works ' +
          '(post-OOBE)',
      () => {
        setMode(false /* isOobeMode */);

        return setVisiblePage(PASSWORD)
            .then(() => {
              return enterPassword(CORRECT_PASSWORD);
            })
            .then(() => {
              multiDeviceSetupElement.delegate.shouldSetHostSucceed = true;
              const whenPageChanges = eventToPromise(
                  'visible-page-name-changed', multiDeviceSetupElement);
              forwardButton.click();
              return whenPageChanges;
            })
            .then(() => {
              assertEquals(SUCCESS, multiDeviceSetupElement.visiblePageName);
              assertEquals(1, getNumSetHostDeviceCalls());
            });
      });

  test(
      'PasswordPage forward button does nothing if invalid password ' +
          '(post-OOBE)',
      () => {
        setMode(false /* isOobeMode */);

        return setVisiblePage(PASSWORD)
            .then(() => {
              return enterPassword(WRONG_PASSWORD);
            })
            .then(() => {
              multiDeviceSetupElement.delegate.shouldSetHostSucceed = true;
              forwardButton.click();
              flush();
              return waitBeforeNextRender(multiDeviceSetupElement);
            })
            .then(() => {
              assertEquals(PASSWORD, multiDeviceSetupElement.visiblePageName);
              assertEquals(0, getNumSetHostDeviceCalls());
            });
      });

  test(
      'PasswordPage forward button is disabled if invalid password ' +
          '(post-OOBE)',
      () => {
        const whenMultiDeviceSetupLoads = setMode(false /* isOobeMode */);

        return setVisiblePage(PASSWORD)
            .then(() => {
              return enterPassword(WRONG_PASSWORD);
            })
            .then(() => {
              forwardButton.click();
              flush();
              return waitBeforeNextRender(multiDeviceSetupElement);
            })
            .then(() => {
              assertTrue(multiDeviceSetupElement.forwardButtonDisabled);
            });
      });
});