chromium/chrome/test/data/webui/chromeos/cloud_upload/move_confirmation_page_test.ts

// Copyright 2023 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://cloud-upload/move_confirmation_page.js';

import {OperationType, UserAction} from 'chrome://cloud-upload/cloud_upload.mojom-webui.js';
import {CloudUploadBrowserProxy} from 'chrome://cloud-upload/cloud_upload_browser_proxy.js';
import {CloudProvider, MoveConfirmationPageElement} from 'chrome://cloud-upload/move_confirmation_page.js';
import {CrCheckboxElement} from 'chrome://resources/ash/common/cr_elements/cr_checkbox/cr_checkbox.js';
import {CrosLottieEvent} from 'chrome://resources/cros_components/lottie_renderer/lottie-renderer.js';
import {assert} from 'chrome://resources/js/assert.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
import {assertDeepEquals, assertEquals, assertFalse, assertNotReached, assertTrue} from 'chrome://webui-test/chai_assert.js';

import {CloudUploadTestBrowserProxy, ProxyOptions} from './cloud_upload_test_browser_proxy.js';

suite('<move-confirmation-page>', () => {
  /* Holds the <move-confirmation-page> app. */
  let container: HTMLDivElement;
  /* The <move-confirmation-page> app. */
  let moveConfirmationPageApp: MoveConfirmationPageElement;
  /* The BrowserProxy element to make assertions on when mojo methods are
     called. */
  let testProxy: CloudUploadTestBrowserProxy;

  async function setUp(options: ProxyOptions) {
    testProxy = new CloudUploadTestBrowserProxy(options);
    CloudUploadBrowserProxy.setInstance(testProxy);

    // Setup fake strings, there are tests below to assert these strings.
    loadTimeData.resetForTesting({
      'moveAndOpen': 'Move and open',
      'copyAndOpen': 'Copy and open',
      'moveConfirmationMoveTitle': 'Move 1 file to $1',
      'moveConfirmationMoveTitlePlural': 'Move $2 files to $1',
      'moveConfirmationCopyTitle': 'Copy 1 file to $1',
      'moveConfirmationCopyTitlePlural': 'Copy $2 files to $1',
      'moveConfirmationOneDriveBodyText': 'OneDrive body',
      'moveConfirmationGoogleDriveBodyText': 'Google Drive body',
      'moveConfirmationAlwaysMove': 'Don\'t ask again',
      'oneDrive': 'Microsoft OneDrive',
      'googleDrive': 'Google Drive',
    });

    // Define promise to wait for a `CrosLottieEvent.INITIALIZED` event.
    let resolveFunction: () => void;
    const animationInitializedPromise = new Promise<void>((resolve) => {
      resolveFunction = resolve;
    });
    document.addEventListener(CrosLottieEvent.INITIALIZED, () => {
      resolveFunction();
    });

    // Creates and attaches the <move-confirmation-page> element to the DOM
    // tree.
    moveConfirmationPageApp =
        document.createElement('move-confirmation-page') as
        MoveConfirmationPageElement;
    container.appendChild(moveConfirmationPageApp);

    // Initialise dialog
    if (options.dialogSpecificArgs.moveConfirmationOneDriveDialogArgs) {
      await moveConfirmationPageApp.setDialogAttributes(
          1,
          options.dialogSpecificArgs.moveConfirmationOneDriveDialogArgs
              .operationType,
          CloudProvider.ONE_DRIVE);
    } else if (options.dialogSpecificArgs
                   .moveConfirmationGoogleDriveDialogArgs) {
      await moveConfirmationPageApp.setDialogAttributes(
          1,
          options.dialogSpecificArgs.moveConfirmationGoogleDriveDialogArgs
              .operationType,
          CloudProvider.GOOGLE_DRIVE);
    } else {
      assertNotReached();
    }

    // Ensure that the animation within the move confirmation page has been
    // initialized to avoid race conditions when the test exits.
    await animationInitializedPromise;
  }

  /**
   * Runs prior to all the tests running, attaches a div to enable isolated
   * clearing and attaching of the web component.
   */
  suiteSetup(() => {
    container = document.createElement('div');
    document.body.appendChild(container);
  });

  /**
   * Runs after each test. Removes all elements from the <div> that holds
   * the <move-confirmation-page> component.
   */
  teardown(() => {
    moveConfirmationPageApp.$('.action-button').click();
    loadTimeData.resetForTesting();
    assert(window.trustedTypes);
    container.innerHTML = window.trustedTypes.emptyHTML;
    testProxy.handler.reset();
  });

  /**
   * Test that the checkbox does not appear if the move confirmation page has
   * not been shown before for Google Drive when the cloud provider is Google
   * Drive. Test that clicking the action button calls the right mojo request.
   */
  test('No checkbox before first move confirmation for Drive', async () => {
    await setUp({
      fileNames: ['text.docx'],
      officeWebAppInstalled: true,
      installOfficeWebAppResult: true,
      odfsMounted: true,
      dialogSpecificArgs: {
        moveConfirmationGoogleDriveDialogArgs: {
          operationType: OperationType.kMove,
        },
      },
      officeMoveConfirmationShownForDrive: false,
    });
    const checkbox = moveConfirmationPageApp.$<CrCheckboxElement>(
        '#always-copy-or-move-checkbox');
    assertFalse(!!checkbox);

    moveConfirmationPageApp.$('.action-button').click();

    // Check that the right |respondWithUserActionAndClose| mojo request is
    // called.
    await testProxy.handler.whenCalled('respondWithUserActionAndClose');
    assertEquals(
        1, testProxy.handler.getCallCount('respondWithUserActionAndClose'));
    assertDeepEquals(
        [UserAction.kUploadToGoogleDrive],
        testProxy.handler.getArgs('respondWithUserActionAndClose'));

    // Check that the |setAlwaysMoveOfficeFilesToDrive| mojo request is
    // called with |false|.
    await testProxy.handler.whenCalled('respondWithUserActionAndClose');
    assertEquals(
        1, testProxy.handler.getCallCount('setAlwaysMoveOfficeFilesToDrive'));
    assertDeepEquals(
        [false], testProxy.handler.getArgs('setAlwaysMoveOfficeFilesToDrive'));
  });

  /**
   * Test that the checkbox does appear if the move confirmation page has been
   * shown before for Google Drive when the cloud provider is Google Drive.
   * Test that clicking the checkbox and the action button calls the right mojo
   * requests.
   */
  test(
      'Checkbox after first move confirmation for Drive. Checkbox clicked',
      async () => {
        await setUp({
          fileNames: ['text.docx'],
          officeWebAppInstalled: true,
          installOfficeWebAppResult: true,
          odfsMounted: true,
          dialogSpecificArgs: {
            moveConfirmationGoogleDriveDialogArgs: {
              operationType: OperationType.kMove,
            },
          },
          alwaysMoveOfficeFilesToDrive: false,
          alwaysMoveOfficeFilesToOneDrive: true,
          officeMoveConfirmationShownForDrive: true,
        });
        const checkbox = moveConfirmationPageApp.$<CrCheckboxElement>(
            '#always-copy-or-move-checkbox');
        assertTrue(!!checkbox);

        // Click checkbox.
        assertFalse(checkbox.checked);
        checkbox.checked = true;

        moveConfirmationPageApp.$('.action-button').click();

        // Check that the right |respondWithUserActionAndClose| mojo request is
        // called.
        await testProxy.handler.whenCalled('respondWithUserActionAndClose');
        assertEquals(
            1, testProxy.handler.getCallCount('respondWithUserActionAndClose'));
        assertDeepEquals(
            [UserAction.kUploadToGoogleDrive],
            testProxy.handler.getArgs('respondWithUserActionAndClose'));

        // Check that the right |setAlwaysMoveOfficeFilesToDrive| mojo request
        // is called with |true|.
        assertEquals(
            1,
            testProxy.handler.getCallCount('setAlwaysMoveOfficeFilesToDrive'));
        assertDeepEquals(
            [true],
            testProxy.handler.getArgs('setAlwaysMoveOfficeFilesToDrive'));

        // Check that the |setAlwaysMoveOfficeFilesToOneDrive| mojo request is
        // not called.
        assertEquals(
            0,
            testProxy.handler.getCallCount(
                'setAlwaysMoveOfficeFilesToOneDrive'));
      });

  /**
   * Test that the checkbox does appear if the move confirmation page has been
   * shown before for Google Drive when the cloud provider is Google Drive.
   * Test that clicking the action button calls the right mojo request.
   */
  test(
      'Checkbox after first move confirmation for Drive. Checkbox not clicked',
      async () => {
        await setUp({
          fileNames: ['text.docx'],
          officeWebAppInstalled: true,
          installOfficeWebAppResult: true,
          odfsMounted: true,
          dialogSpecificArgs: {
            moveConfirmationGoogleDriveDialogArgs: {
              operationType: OperationType.kMove,
            },
          },
          alwaysMoveOfficeFilesToDrive: false,
          alwaysMoveOfficeFilesToOneDrive: true,
          officeMoveConfirmationShownForDrive: true,
        });
        const checkbox = moveConfirmationPageApp.$<CrCheckboxElement>(
            '#always-copy-or-move-checkbox');
        assertTrue(!!checkbox);

        // Don't click checkbox.
        assertFalse(checkbox.checked);

        moveConfirmationPageApp.$('.action-button').click();

        // Check that the right |respondWithUserActionAndClose| mojo request is
        // called.
        await testProxy.handler.whenCalled('respondWithUserActionAndClose');
        assertEquals(
            1, testProxy.handler.getCallCount('respondWithUserActionAndClose'));
        assertDeepEquals(
            [UserAction.kUploadToGoogleDrive],
            testProxy.handler.getArgs('respondWithUserActionAndClose'));

        // Check that the |setAlwaysMoveOfficeFilesToDrive| mojo request is
        // called with |false|.
        await testProxy.handler.whenCalled('respondWithUserActionAndClose');
        assertEquals(
            1,
            testProxy.handler.getCallCount('setAlwaysMoveOfficeFilesToDrive'));
        assertDeepEquals(
            [false],
            testProxy.handler.getArgs('setAlwaysMoveOfficeFilesToDrive'));
      });

  /**
   * Test that the checkbox doesn't appear if the move confirmation page has
   * been shown before for OneDrive but the cloud provider is Google Drive.
   */
  test(
      'No checkbox before first move confirmation for Drive but after move ' +
          'confirmation for OneDrive has already been shown',
      async () => {
        await setUp({
          fileNames: ['text.docx'],
          officeWebAppInstalled: true,
          installOfficeWebAppResult: true,
          odfsMounted: true,
          dialogSpecificArgs: {
            moveConfirmationGoogleDriveDialogArgs: {
              operationType: OperationType.kMove,
            },
          },
          officeMoveConfirmationShownForDrive: false,
          officeMoveConfirmationShownForOneDrive: true,
        });
        const hasCheckbox = moveConfirmationPageApp.$<CrCheckboxElement>(
                                '#always-copy-or-move-checkbox') !== null;
        assertFalse(hasCheckbox);
      });

  /**
   * Test that the checkbox does not appear if the move confirmation page has
   * not been shown before for OneDrive when the cloud provider is OneDrive.
   * Test that clicking the action button calls the right mojo request.
   */
  test('No checkbox before first move confirmation for OneDrive', async () => {
    await setUp({
      fileNames: ['text.docx'],
      officeWebAppInstalled: true,
      installOfficeWebAppResult: true,
      odfsMounted: true,
      dialogSpecificArgs: {
        moveConfirmationOneDriveDialogArgs: {
          operationType: OperationType.kMove,
        },
      },
      officeMoveConfirmationShownForOneDrive: false,
    });
    const hasCheckbox = moveConfirmationPageApp.$<CrCheckboxElement>(
                            '#always-copy-or-move-checkbox') !== null;
    assertFalse(hasCheckbox);

    moveConfirmationPageApp.$('.action-button').click();

    // Check that the right |respondWithUserActionAndClose| mojo request is
    // called.
    await testProxy.handler.whenCalled('respondWithUserActionAndClose');
    assertEquals(
        1, testProxy.handler.getCallCount('respondWithUserActionAndClose'));
    assertDeepEquals(
        [UserAction.kUploadToOneDrive],
        testProxy.handler.getArgs('respondWithUserActionAndClose'));

    // Check that the |setAlwaysMoveOfficeFilesToOneDrive| mojo request is
    // called with |false|.
    await testProxy.handler.whenCalled('respondWithUserActionAndClose');
    assertEquals(
        1,
        testProxy.handler.getCallCount('setAlwaysMoveOfficeFilesToOneDrive'));
    assertDeepEquals(
        [false],
        testProxy.handler.getArgs('setAlwaysMoveOfficeFilesToOneDrive'));
  });

  /**
   * Test that the checkbox does not appear if the move confirmation page has
   * not been shown before for OneDrive when the cloud provider is OneDrive.
   * Test that clicking the checkbox and the action button calls the right mojo
   * requests.
   */
  test(
      'Checkbox after first move confirmation for OneDrive. Checkbox clicked',
      async () => {
        await setUp({
          fileNames: ['text.docx'],
          officeWebAppInstalled: true,
          installOfficeWebAppResult: true,
          odfsMounted: true,
          dialogSpecificArgs: {
            moveConfirmationOneDriveDialogArgs: {
              operationType: OperationType.kMove,
            },
          },
          alwaysMoveOfficeFilesToDrive: true,
          alwaysMoveOfficeFilesToOneDrive: false,
          officeMoveConfirmationShownForOneDrive: true,
        });
        const checkbox = moveConfirmationPageApp.$<CrCheckboxElement>(
            '#always-copy-or-move-checkbox');
        assertTrue(!!checkbox);

        // Click checkbox.
        assertFalse(checkbox.checked);
        checkbox.checked = true;

        moveConfirmationPageApp.$('.action-button').click();

        // Check that the right |respondWithUserActionAndClose| mojo request is
        // called.
        await testProxy.handler.whenCalled('respondWithUserActionAndClose');
        assertEquals(
            1, testProxy.handler.getCallCount('respondWithUserActionAndClose'));
        assertDeepEquals(
            [UserAction.kUploadToOneDrive],
            testProxy.handler.getArgs('respondWithUserActionAndClose'));

        // Check that the right |setAlwaysMoveOfficeFilesToOneDrive| mojo
        // request is called.
        assertEquals(
            1,
            testProxy.handler.getCallCount(
                'setAlwaysMoveOfficeFilesToOneDrive'));
        assertDeepEquals(
            [true],
            testProxy.handler.getArgs('setAlwaysMoveOfficeFilesToOneDrive'));


        // Check that the |setAlwaysMoveOfficeFilesToDrive| mojo request is not
        // called.
        assertEquals(
            0,
            testProxy.handler.getCallCount('setAlwaysMoveOfficeFilesToDrive'));
      });


  /**
   * Test that the checkbox does appear if the move confirmation page has been
   * shown before for OneDrive when the cloud provider is OneDrive.
   * Test that clicking the action button calls the right mojo request.
   */
  test(
      'Checkbox after first move confirmation for OneDrive. Checkbox not ' +
          'clicked',
      async () => {
        await setUp({
          fileNames: ['text.docx'],
          officeWebAppInstalled: true,
          installOfficeWebAppResult: true,
          odfsMounted: true,
          dialogSpecificArgs: {
            moveConfirmationOneDriveDialogArgs: {
              operationType: OperationType.kMove,
            },
          },
          alwaysMoveOfficeFilesToDrive: true,
          alwaysMoveOfficeFilesToOneDrive: false,
          officeMoveConfirmationShownForOneDrive: true,
        });
        const checkbox = moveConfirmationPageApp.$<CrCheckboxElement>(
            '#always-copy-or-move-checkbox');
        assertTrue(!!checkbox);

        // Don't click checkbox.
        assertFalse(checkbox.checked);

        moveConfirmationPageApp.$('.action-button').click();

        // Check that the right |respondWithUserActionAndClose| mojo request is
        // called.
        await testProxy.handler.whenCalled('respondWithUserActionAndClose');
        assertEquals(
            1, testProxy.handler.getCallCount('respondWithUserActionAndClose'));
        assertDeepEquals(
            [UserAction.kUploadToOneDrive],
            testProxy.handler.getArgs('respondWithUserActionAndClose'));

        // Check that the |setAlwaysMoveOfficeFilesToOneDrive| mojo request is
        // called with |false|.
        await testProxy.handler.whenCalled('respondWithUserActionAndClose');
        assertEquals(
            1,
            testProxy.handler.getCallCount(
                'setAlwaysMoveOfficeFilesToOneDrive'));
        assertDeepEquals(
            [false],
            testProxy.handler.getArgs('setAlwaysMoveOfficeFilesToOneDrive'));
      });

  /**
   * Test that the checkbox doesn't appear if the move confirmation page has
   * been shown before for Google Drive but the cloud provider is OneDrive.
   */
  test(
      'No checkbox before first move confirmation for OneDrive but after ' +
          'move confirmation for Drive has already been shown',
      async () => {
        await setUp({
          fileNames: ['text.docx'],
          officeWebAppInstalled: true,
          installOfficeWebAppResult: true,
          odfsMounted: true,
          dialogSpecificArgs: {
            moveConfirmationOneDriveDialogArgs: {
              operationType: OperationType.kMove,
            },
          },
          officeMoveConfirmationShownForOneDrive: false,
        });
        const hasCheckbox = moveConfirmationPageApp.$<CrCheckboxElement>(
                                '#always-copy-or-move-checkbox') !== null;
        assertFalse(hasCheckbox);
      });


  /**
   * Test that the checkbox is pre-checked if the "Always move to Drive"
   * preference is set to true.
   */
  test('Checkbox pre-checked for Drive', async () => {
    await setUp({
      fileNames: ['text.docx'],
      officeWebAppInstalled: true,
      installOfficeWebAppResult: true,
      odfsMounted: true,
      dialogSpecificArgs: {
        moveConfirmationGoogleDriveDialogArgs: {
          operationType: OperationType.kMove,
        },
      },
      alwaysMoveOfficeFilesToDrive: true,
      alwaysMoveOfficeFilesToOneDrive: false,
      officeMoveConfirmationShownForDrive: true,
    });
    const checkbox = moveConfirmationPageApp.$<CrCheckboxElement>(
        '#always-copy-or-move-checkbox');
    assertTrue(!!checkbox);
    assertTrue(checkbox.checked);
  });

  /**
   * Test that the checkbox is pre-checked if the "Always move to OneDrive"
   * preference is set to true.
   */
  test('Checkbox pre-checked for OneDrive', async () => {
    await setUp({
      fileNames: ['text.docx'],
      officeWebAppInstalled: true,
      installOfficeWebAppResult: true,
      odfsMounted: true,
      dialogSpecificArgs: {
        moveConfirmationOneDriveDialogArgs: {
          operationType: OperationType.kMove,
        },
      },
      alwaysMoveOfficeFilesToDrive: false,
      alwaysMoveOfficeFilesToOneDrive: true,
      officeMoveConfirmationShownForOneDrive: true,
    });
    const checkbox = moveConfirmationPageApp.$<CrCheckboxElement>(
        '#always-copy-or-move-checkbox');
    assertTrue(!!checkbox);
    assertTrue(checkbox.checked);
  });

  /**
   * Check the dialog's text when the cloud provider is Drive.
   */
  test('DialogTextForDrive', async () => {
    await setUp({
      fileNames: ['text.docx'],
      officeWebAppInstalled: true,
      installOfficeWebAppResult: true,
      odfsMounted: true,
      dialogSpecificArgs: {
        moveConfirmationGoogleDriveDialogArgs: {
          operationType: OperationType.kMove,
        },
      },
      officeMoveConfirmationShownForDrive: true,
    });
    // Title.
    const titleElement = moveConfirmationPageApp.$<HTMLElement>('#title')!;
    assertTrue(titleElement.innerText.includes('Google Drive'));

    // Body.
    const bodyText = moveConfirmationPageApp.$('#body-text');
    assertTrue(bodyText.innerText.includes('Google Drive'));

    // Checkbox.
    const checkbox = moveConfirmationPageApp.$<CrCheckboxElement>(
        '#always-copy-or-move-checkbox');
    assertTrue(!!checkbox);
    assertTrue(checkbox.innerText.includes('Don\'t ask again'));
  });

  /**
   * Check the dialog's text when the cloud provider is OneDrive.
   */
  test('DialogTextForOneDrive', async () => {
    await setUp({
      fileNames: ['text.docx'],
      officeWebAppInstalled: true,
      installOfficeWebAppResult: true,
      odfsMounted: true,
      dialogSpecificArgs: {
        moveConfirmationOneDriveDialogArgs: {
          operationType: OperationType.kMove,
        },
      },
      officeMoveConfirmationShownForOneDrive: true,
    });
    // Title.
    const titleElement = moveConfirmationPageApp.$<HTMLElement>('#title')!;
    assertTrue(titleElement.innerText.includes('Microsoft OneDrive'));

    // Body.
    const bodyText = moveConfirmationPageApp.$('#body-text');
    assertTrue(bodyText.innerText.includes('OneDrive'));

    // Checkbox.
    const checkbox = moveConfirmationPageApp.$<CrCheckboxElement>(
        '#always-copy-or-move-checkbox');
    assertTrue(!!checkbox);
    assertTrue(checkbox.innerText.includes('Don\'t ask again'));
  });

  /**
   * Check the dialog's text when the operation type is 'Move'.
   */
  test('DialogTextForMoveAndUpload', async () => {
    await setUp({
      fileNames: ['text.docx'],
      officeWebAppInstalled: true,
      installOfficeWebAppResult: true,
      odfsMounted: true,
      dialogSpecificArgs: {
        moveConfirmationGoogleDriveDialogArgs: {
          operationType: OperationType.kMove,
        },
      },
      officeMoveConfirmationShownForDrive: true,
    });
    // Title.
    const titleElement = moveConfirmationPageApp.$<HTMLElement>('#title')!;
    assertTrue(titleElement.innerText.includes('Move'));

    // Button.
    const actionButton =
        moveConfirmationPageApp.$<HTMLElement>('.action-button')!;
    assertEquals('Move and open', actionButton.innerText);
  });

  /**
   * Check the dialog's text when the operation type is 'Copy'.
   */
  test('DialogTextForCopyAndUpload', async () => {
    await setUp({
      fileNames: ['text.docx'],
      officeWebAppInstalled: true,
      installOfficeWebAppResult: true,
      odfsMounted: true,
      dialogSpecificArgs: {
        moveConfirmationGoogleDriveDialogArgs: {
          operationType: OperationType.kCopy,
        },
      },
      officeMoveConfirmationShownForDrive: true,
    });
    // Title.
    const titleElement = moveConfirmationPageApp.$<HTMLElement>('#title')!;
    assertTrue(titleElement.innerText.includes('Copy'));

    // Button.
    const actionButton =
        moveConfirmationPageApp.$<HTMLElement>('.action-button')!;
    assertEquals('Copy and open', actionButton.innerText);
  });

  /**
   * Test that clicking the cancel button triggers the right
   * `respondWithUserActionAndClose` mojo request.
   */
  test('Cancel', async () => {
    await setUp({
      fileNames: ['text.docx'],
      officeWebAppInstalled: true,
      installOfficeWebAppResult: true,
      odfsMounted: true,
      dialogSpecificArgs: {
        moveConfirmationGoogleDriveDialogArgs: {
          operationType: OperationType.kCopy,
        },
      },
      officeMoveConfirmationShownForDrive: true,
    });

    moveConfirmationPageApp.$('.cancel-button').click();
    await testProxy.handler.whenCalled('respondWithUserActionAndClose');
    assertEquals(
        1, testProxy.handler.getCallCount('respondWithUserActionAndClose'));
    assertDeepEquals(
        [UserAction.kCancelGoogleDrive],
        testProxy.handler.getArgs('respondWithUserActionAndClose'));
  });

  /**
   * Test that an Escape keydown triggers the right
   * `respondWithUserActionAndClose` mojo request.
   */
  test('Escape', async () => {
    await setUp({
      fileNames: ['text.docx'],
      officeWebAppInstalled: true,
      installOfficeWebAppResult: true,
      odfsMounted: true,
      dialogSpecificArgs: {
        moveConfirmationGoogleDriveDialogArgs: {
          operationType: OperationType.kCopy,
        },
      },
      officeMoveConfirmationShownForDrive: true,
    });

    document.dispatchEvent(new KeyboardEvent('keydown', {key: 'Escape'}));
    await testProxy.handler.whenCalled('respondWithUserActionAndClose');
    assertEquals(
        1, testProxy.handler.getCallCount('respondWithUserActionAndClose'));
    assertDeepEquals(
        [UserAction.kCancelGoogleDrive],
        testProxy.handler.getArgs('respondWithUserActionAndClose'));
  });
});