chromium/chrome/test/data/webui/chromeos/shimless_rma/onboarding_select_components_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 {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 {fakeComponentsForRepairStateTest} from 'chrome://shimless-rma/fake_data.js';
import {FakeShimlessRmaService} from 'chrome://shimless-rma/fake_shimless_rma_service.js';
import {setShimlessRmaServiceForTesting} from 'chrome://shimless-rma/mojo_interface_provider.js';
import {OnboardingSelectComponentsPageElement} from 'chrome://shimless-rma/onboarding_select_components_page.js';
import {RepairComponentChip} from 'chrome://shimless-rma/repair_component_chip.js';
import {ShimlessRma} from 'chrome://shimless-rma/shimless_rma.js';
import {Component, ComponentRepairStatus, StateResult} from 'chrome://shimless-rma/shimless_rma.mojom-webui.js';
import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';

suite('onboardingSelectComponentsPageTest', function() {
  let component: OnboardingSelectComponentsPageElement|null = null;

  let service: FakeShimlessRmaService|null = null;

  // ShimlessRma is needed to handle the 'transition-state' event used by the
  // rework button.
  let shimlessRmaComponent: ShimlessRma|null = null;

  const componentButtonSelector = '#componentButton';
  const reworkFlowLinkSelector = '#reworkFlowLink';
  const cameraSelector = '#componentCamera';
  const batterySelector = '#componentBattery';
  const touchpadSelector = '#componentTouchpad';

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

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

  function initializeComponentSelectPage(deviceComponents: Component[]):
      Promise<void> {
    // Initialize the fake data.
    assert(service);
    service.setGetComponentListResult(deviceComponents);

    assert(!shimlessRmaComponent);
    shimlessRmaComponent = document.createElement(ShimlessRma.is);
    assert(shimlessRmaComponent);
    document.body.appendChild(shimlessRmaComponent);

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

    return flushTasks();
  }

  function clickComponentCameraToggle(): Promise<void> {
    assert(component);
    const cameraComponent =
        strictQuery(cameraSelector, component.shadowRoot, RepairComponentChip);
    assertFalse(cameraComponent.disabled);
    strictQuery(
        componentButtonSelector, cameraComponent.shadowRoot, CrButtonElement)
        .click();
    return flushTasks();
  }

  function clickReworkButton(): Promise<void> {
    assert(component);
    strictQuery(reworkFlowLinkSelector, component.shadowRoot, HTMLElement)
        .click();
    return flushTasks();
  }

  // Verify the page is initialized with the expected components.
  test('PageInitializes', async () => {
    await initializeComponentSelectPage(fakeComponentsForRepairStateTest);

    assert(component);
    const reworkFlowLink =
        strictQuery(reworkFlowLinkSelector, component.shadowRoot, HTMLElement);
    assertFalse(reworkFlowLink.hidden);

    const cameraComponent =
        strictQuery(cameraSelector, component.shadowRoot, RepairComponentChip);
    assertEquals('Camera', cameraComponent.componentName);
    assertEquals('Camera_XYZ_1', cameraComponent.componentIdentifier);
    assertFalse(cameraComponent.disabled);
    assertFalse(cameraComponent.checked);

    const batteryComponent =
        strictQuery(batterySelector, component.shadowRoot, RepairComponentChip);
    assertEquals('Battery', batteryComponent.componentName);
    assertEquals('Battery_XYZ_Lithium', batteryComponent.componentIdentifier);
    assertTrue(batteryComponent.disabled);
    assertFalse(batteryComponent.checked);

    const touchpadComponent = strictQuery(
        touchpadSelector, component.shadowRoot, RepairComponentChip);
    assertEquals('Touchpad', touchpadComponent.componentName);
    assertEquals('Touchpad_XYZ_2', touchpadComponent.componentIdentifier);
    assertFalse(touchpadComponent.disabled);
    assertTrue(touchpadComponent.checked);
  });

  // Verify toggling a component updates its state.
  test('ToggleComponent', async () => {
    await initializeComponentSelectPage(fakeComponentsForRepairStateTest);

    assert(component);
    let cameraComponent =
        component.getComponentRepairStateListForTesting().find(
            (repairComponent: Component) =>
                repairComponent.identifier === 'Camera_XYZ_1');
    assert(cameraComponent);
    assertEquals(ComponentRepairStatus.kOriginal, cameraComponent.state);

    // Click the camera component button and expect the state to change.
    await clickComponentCameraToggle();
    cameraComponent = component.getComponentRepairStateListForTesting().find(
        (repairComponent: Component) =>
            repairComponent.identifier === 'Camera_XYZ_1');
    assert(cameraComponent);
    assertEquals(ComponentRepairStatus.kReplaced, cameraComponent.state);
  });

  // Verify clicking the rework link makes the correct call.
  test('ReworkCallsReworkMainboard', async () => {
    await initializeComponentSelectPage(fakeComponentsForRepairStateTest);

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

    await clickReworkButton();

    const expectedCallCount = 1;
    assertEquals(expectedCallCount, callCounter);
  });

  // Verify clicking the next button sets the component list.
  test('OnNextCallsSetComponentList', async () => {
    await initializeComponentSelectPage(fakeComponentsForRepairStateTest);

    const resolver = new PromiseResolver<{stateResult: StateResult}>();
    let callCounter = 0;
    assert(service);
    service.setComponentList = (components: Component[]) => {
      assertDeepEquals(fakeComponentsForRepairStateTest, components);
      ++callCounter;
      return resolver.promise;
    };

    assert(component);
    component.onNextButtonClick();
    await resolver;

    const expectedCallCount = 1;
    assertEquals(expectedCallCount, callCounter);
  });

  // Verify all components are disabled when `allButtonsDisabled` is set.
  test('DisablesComponents', async () => {
    await initializeComponentSelectPage(fakeComponentsForRepairStateTest);

    assert(component);
    // Select the two known enabled components and verify they become disabled.
    const cameraComponent =
        strictQuery(cameraSelector, component.shadowRoot, RepairComponentChip);
    const touchpadComponent = strictQuery(
        touchpadSelector, component.shadowRoot, RepairComponentChip);
    assertFalse(cameraComponent.disabled);
    assertFalse(touchpadComponent.disabled);

    component.allButtonsDisabled = true;
    assertTrue(cameraComponent.disabled);
    assertTrue(touchpadComponent.disabled);
  });

  // Verify clicking rework link has no response when `allButtonsDisabled` is
  // set.
  test('ReworkLinkDisabled', async () => {
    await initializeComponentSelectPage(fakeComponentsForRepairStateTest);

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

    assert(component);
    component.allButtonsDisabled = true;
    await clickReworkButton();

    const expectedCallCount = 0;
    assertEquals(expectedCallCount, callCounter);
  });
});