chromium/chrome/test/data/webui/chromeos/shimless_rma/reimaging_provisioning_page_test.ts

// Copyright 2021 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://shimless-rma/shimless_rma.js';

import {CrButtonElement} from 'chrome://resources/ash/common/cr_elements/cr_button/cr_button.js';
import {CrDialogElement} from 'chrome://resources/ash/common/cr_elements/cr_dialog/cr_dialog.js';
import {PromiseResolver} from 'chrome://resources/ash/common/promise_resolver.js';
import {strictQuery} from 'chrome://resources/ash/common/typescript_utils/strict_query.js';
import {assert} from 'chrome://resources/js/assert.js';
import {FATAL_HARDWARE_ERROR} from 'chrome://shimless-rma/events.js';
import {FakeShimlessRmaService} from 'chrome://shimless-rma/fake_shimless_rma_service.js';
import {setShimlessRmaServiceForTesting} from 'chrome://shimless-rma/mojo_interface_provider.js';
import {PROVISIONING_ERROR_CODE_PREFIX, ReimagingProvisioningPage} from 'chrome://shimless-rma/reimaging_provisioning_page.js';
import {ShimlessRma} from 'chrome://shimless-rma/shimless_rma.js';
import {ProvisioningError, ProvisioningStatus, RmadErrorCode, StateResult} from 'chrome://shimless-rma/shimless_rma.mojom-webui.js';
import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
import {eventToPromise} from 'chrome://webui-test/test_util.js';

suite('reimagingProvisioningPageTest', function() {
  /**
   * ShimlessRma is needed to handle the 'transition-state' event used
   * when handling calibration overall progress signals.
   */
  let shimlessRmaComponent: ShimlessRma|null = null;

  let component: ReimagingProvisioningPage|null = null;

  const service: FakeShimlessRmaService = new FakeShimlessRmaService();

  const wpEnabledDialogSelector = '#wpEnabledDialog';
  const tryAgainButtonSelector = '#tryAgainButton';

  setup(() => {
    document.body.innerHTML = window.trustedTypes!.emptyHTML;
    setShimlessRmaServiceForTesting(service);
  });

  teardown(() => {
    component?.remove();
    component = null;
    shimlessRmaComponent?.remove();
    shimlessRmaComponent = null;
    service.reset();
  });

  function initializeWaitForProvisioningPage(): Promise<void> {
    assert(!shimlessRmaComponent);
    shimlessRmaComponent = document.createElement(ShimlessRma.is);
    assert(shimlessRmaComponent);
    document.body.appendChild(shimlessRmaComponent);

    assert(!component);
    component = document.createElement(ReimagingProvisioningPage.is);
    assert(component);
    document.body.appendChild(component);

    return flushTasks();
  }

  // Verify when provisioning progress reaches 100%, the complete action is
  // called.
  test('ProvisioningCompleteTransitionsState', async () => {
    await initializeWaitForProvisioningPage();

    let provisioningComplete = false;
    const resolver = new PromiseResolver<{stateResult: StateResult}>();
    service.provisioningComplete = () => {
      provisioningComplete = true;
      return resolver.promise;
    };

    service.triggerProvisioningObserver(
        ProvisioningStatus.kComplete, /* progress= */ 1.0,
        ProvisioningError.kUnknown,
        /* delayMs= */ 0);
    await flushTasks();

    assertTrue(provisioningComplete);
  });

  // Verify the error dialog shows for a WP error and provisioning can be
  // retried.
  test('ProvisioningFailedWpError', async () => {
    await initializeWaitForProvisioningPage();

    let callCount = 0;
    const resolver = new PromiseResolver<{stateResult: StateResult}>();
    service.retryProvisioning = () => {
      ++callCount;
      return resolver.promise;
    };

    // Confirm the dialog is closed, trigger a failure then confirm the dialog
    // opens.
    assert(component);
    const wpEnabledDialog = strictQuery(
        wpEnabledDialogSelector, component.shadowRoot, CrDialogElement);
    assertFalse(wpEnabledDialog.open);
    service.triggerProvisioningObserver(
        ProvisioningStatus.kFailedBlocking, /* progress= */ 1.0,
        ProvisioningError.kWpEnabled,
        /* delayMs= */ 0);
    await flushTasks();
    assertTrue(wpEnabledDialog.open);

    // Click the try again button.
    strictQuery(tryAgainButtonSelector, component.shadowRoot, CrButtonElement)
        .click();
    assertFalse(wpEnabledDialog.open);
    assertEquals(1, callCount);
  });

  // Verify the the fatal hardware error dialog shows for a non-WP error.
  test('ProvisioningFailedNonWpError', async () => {
    await initializeWaitForProvisioningPage();

    // Trigger a blocking error.
    assert(component);
    const fatalHardwareErrorEvent =
        eventToPromise(FATAL_HARDWARE_ERROR, component);
    const expectedProvisoningError = ProvisioningError.kInternal;
    service.triggerProvisioningObserver(
        ProvisioningStatus.kFailedBlocking, 1.0, expectedProvisoningError, 0);
    await flushTasks();

    // Confirm the correct error code is displayed.
    const eventResponse = await fatalHardwareErrorEvent;
    assertEquals(
        RmadErrorCode.kProvisioningFailed, eventResponse.detail.rmadErrorCode);
    assertEquals(
        PROVISIONING_ERROR_CODE_PREFIX + expectedProvisoningError,
        eventResponse.detail.fatalErrorCode);
    assertFalse(
        strictQuery(
            wpEnabledDialogSelector, component.shadowRoot, CrDialogElement)
            .open);
  });
});