chromium/ui/file_manager/file_manager/foreground/elements/files_xf_elements_unittest.ts

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import './xf_button.js';
import './xf_circular_progress.js';
import './xf_display_panel.js';
import './xf_panel_item.js';

import {assert} from 'chrome://resources/js/assert.js';
import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';

import {waitUntil} from '../../common/js/test_error_reporting.js';
import {mockPluralStringProxy} from '../../common/js/unittest_util.js';

import type {PanelButton} from './xf_button.js';
import type {CircularProgress} from './xf_circular_progress.js';
import type {DisplayPanel} from './xf_display_panel.js';
import type {PanelItem} from './xf_panel_item.js';
import {PanelType} from './xf_panel_item.js';

let displayPanel: DisplayPanel;

/**
 * Adds a xf-display-panel element to the test page.
 */
export function setUpPage() {
  mockPluralStringProxy();
  const displayPanelElement = document.createElement('xf-display-panel');
  displayPanelElement.setAttribute('id', 'test-xf-display-panel');
  document.body.appendChild(displayPanelElement);
  displayPanel =
      document.querySelector<DisplayPanel>('#test-xf-display-panel')!;
}

export function tearDown() {
  displayPanel.removeAllPanelItems();
}

/**
 * Tests that adding and removing panels to <xf-display-panel> updates the
 * aria-hidden attribute.
 */
export async function testDisplayPanelAriaHidden() {
  // Starts without any panel so should be hidden;
  assertEquals(displayPanel.getAttribute('aria-hidden'), 'true');

  // Create a panel, but since it isn't attached so the container should still
  // be hidden.
  const progressPanel = displayPanel.createPanelItem('testpanel');
  assertEquals(displayPanel.getAttribute('aria-hidden'), 'true');

  // Attach the Panel. It should make the container visible.
  displayPanel.attachPanelItem(progressPanel);
  assertEquals(displayPanel.getAttribute('aria-hidden'), 'false');

  // Remove the last panel and should be hidden again.
  displayPanel.removePanelItem(progressPanel);
  assertEquals(displayPanel.getAttribute('aria-hidden'), 'true');

  // Add multiple panels, then should be visible.
  displayPanel.addPanelItem('testpanel2');
  displayPanel.addPanelItem('testpanel3');
  assertEquals(displayPanel.getAttribute('aria-hidden'), 'false');

  // Clear all the panels, then should be hidden.
  displayPanel.removeAllPanelItems();
  assertEquals(displayPanel.getAttribute('aria-hidden'), 'true');
}

export async function testDisplayPanelAttachPanel(done: VoidCallback) {
  // Get the host display panel container element.
  const displayPanel =
      document.querySelector<DisplayPanel>('#test-xf-display-panel')!;

  // Test create/attach/remove sequences.
  // Create a progress panel item.
  let progressPanel = displayPanel.createPanelItem('testpanel');
  progressPanel.panelType = PanelType.PROGRESS;

  // Attach the panel to it's host display panel.
  displayPanel.attachPanelItem(progressPanel);

  // Verify the panel is attached to the document.
  assertTrue(!!progressPanel.isConnected);

  // Remove the panel item.
  displayPanel.removePanelItem(progressPanel);

  // Verify the panel item is not attached to the document.
  assertFalse(progressPanel.isConnected);

  // Create a progress panel item.
  progressPanel = displayPanel.createPanelItem('testpanel2');
  progressPanel.panelType = PanelType.PROGRESS;

  // Remove the panel item.
  displayPanel.removePanelItem(progressPanel);

  // Try to attach the removed panel to it's host display panel.
  displayPanel.attachPanelItem(progressPanel);

  // Verify the panel is not attached to the document.
  assertFalse(progressPanel.isConnected);

  done();
}

export async function testDisplayPanelChangingPanelTypes(done: VoidCallback) {
  // Get the host display panel container element.
  const displayPanel =
      document.querySelector<DisplayPanel>('#test-xf-display-panel')!;
  const panelItem = displayPanel.addPanelItem('testpanel');
  panelItem.panelType = PanelType.PROGRESS;

  // Setup the panel item signal (click) callback.
  let signal: string|null = null;
  panelItem.signalCallback = (name) => {
    assert(typeof name === 'string');
    signal = name;
  };

  // Verify the panel item indicator is progress.
  assertEquals(
      panelItem.indicator, 'progress',
      'Wrong panel indicator, got ' + panelItem.indicator);

  // Check cancel signal from the panel from a click.
  let cancel = panelItem.secondaryButton!;
  cancel.click();
  assertEquals(
      signal, 'cancel', 'Expected signal name "cancel". Got ' + signal);

  // Check the progress panel text container has correct aria role.
  const textHost =
      panelItem.shadowRoot!.querySelector<HTMLDivElement>('.xf-panel-text')!;
  assertEquals('alert', textHost.getAttribute('role'));

  // Change the panel item to an error panel.
  panelItem.panelType = PanelType.ERROR;

  // Verify the panel item indicator is set to error.
  assertEquals(
      panelItem.indicator, 'status',
      'Wrong panel indicator, got ' + panelItem.indicator);
  assertEquals(
      panelItem.status, 'failure',
      'Wrong panel status, got ' + panelItem.status);

  // Verify the panel item icon is the failure icon.
  const failIcon = panelItem.shadowRoot!.querySelector('iron-icon')!;
  assertEquals('files36:failure', failIcon.getAttribute('icon'));

  // Check dismiss signal from the panel from a click.
  let dismiss = panelItem.primaryButton!;
  dismiss.click();
  assertEquals(
      signal, 'dismiss', 'Expected signal name "dismiss". Got ' + signal);

  // Change the panel item to an info panel.
  panelItem.panelType = PanelType.INFO;

  // Verify the panel item indicator is set to warning.
  assertEquals(
      panelItem.indicator, 'status',
      'Wrong panel indicator, got ' + panelItem.indicator);
  assertEquals(
      panelItem.status, 'warning',
      'Wrong panel status, got ' + panelItem.status);

  // Verify the panel item icon is the warning icon.
  const warningIcon = panelItem.shadowRoot!.querySelector('iron-icon')!;
  assertEquals('files36:warning', warningIcon.getAttribute('icon'));

  // Check cancel signal from the panel from a click.
  cancel = panelItem.primaryButton!;
  cancel.click();
  assertEquals(
      signal, 'cancel', 'Expected signal name "cancel". Got ' + signal);

  // Change the panel type to a done panel.
  panelItem.panelType = PanelType.DONE;

  // Verify the panel item indicator is set to done.
  assertEquals(
      panelItem.indicator, 'status',
      'Wrong panel indicator, got ' + panelItem.indicator);
  assertEquals(
      panelItem.status, 'success',
      'Wrong panel status, got ' + panelItem.status);

  // Verify the panel item icon is the success icon.
  const successIcon = panelItem.shadowRoot!.querySelector('iron-icon')!;
  assertEquals('files36:success', successIcon.getAttribute('icon'));

  // Check the dimiss signal from the panel from a click.
  signal = 'none';
  dismiss = panelItem.primaryButton!;
  dismiss.click();
  assertEquals(
      signal, 'dismiss', 'Expected signal name "dismiss". Got ' + signal);

  // Change the type to a summary panel.
  panelItem.panelType = PanelType.SUMMARY;

  // Verify the panel item indicator is largeprogress.
  assertEquals(
      panelItem.indicator, 'largeprogress',
      'Wrong panel indicator, got ' + panelItem.indicator);

  // Check no signal emitted from the summary panel from a click.
  const expand = panelItem.primaryButton!;
  signal = 'none';
  expand.click();
  assertEquals(signal, 'none', 'Expected no signal. Got ' + signal);

  // Check the summary panel text container has no aria role.
  assertEquals('', textHost.getAttribute('role'));

  done();
}

export function testFilesDisplayPanelErrorText() {
  // Get the host display panel container element.
  const displayPanel =
      document.querySelector<DisplayPanel>('#test-xf-display-panel')!;

  // Add a panel item to the display panel container.
  const panelItem = displayPanel.addPanelItem('testpanel');

  const text =
      panelItem.shadowRoot!.querySelector<HTMLDivElement>('.xf-panel-text')!;

  // To work with screen readers, the text element should have aria role
  // 'alert'.
  assertEquals('alert', text.getAttribute('role'));

  // Change the primary and secondary text on the panel item.
  panelItem.primaryText = 'foo';
  panelItem.secondaryText = 'bar';

  // Check the primary and secondary text has been set on the panel.
  assertEquals('foo', panelItem.primaryText);
  assertEquals('bar', panelItem.secondaryText);

  // Change the panel item type to an error panel.
  panelItem.panelType = PanelType.ERROR;

  // Check that primary and secondary text don't change.
  assertEquals('foo', panelItem.primaryText);
  assertEquals('bar', panelItem.secondaryText);
}

export async function testFilesDisplayPanelInfo(done: VoidCallback) {
  // Get the host display panel container element.
  const displayPanel =
      document.querySelector<DisplayPanel>('#test-xf-display-panel')!;

  // Add a panel item to the display panel container.
  const panelItem = displayPanel.addPanelItem('testpanel');
  panelItem.dataset['extraButtonText'] = 'Extra button';

  const text =
      panelItem.shadowRoot!.querySelector<HTMLDivElement>('.xf-panel-text')!;

  // To work with screen readers, the text element should have aria role
  // 'alert'.
  assertEquals('alert', text.getAttribute('role'));

  // Change the primary and secondary text on the panel item.
  panelItem.primaryText = 'foo';
  panelItem.secondaryText = 'bar';

  // Check the primary and secondary text has been set on the panel.
  assertEquals('foo', panelItem.primaryText);
  assertEquals('bar', panelItem.secondaryText);

  // Change the panel item type to an info panel.
  panelItem.panelType = PanelType.INFO;

  // Check the primary and secondary text has been set on the panel.
  assertEquals('foo', panelItem.primaryText);
  assertEquals('bar', panelItem.secondaryText);

  // Setup the panel item signal (click) callback.
  let signal: string|null = null;
  panelItem.signalCallback = (name) => {
    assert(typeof name === 'string');
    signal = name;
  };

  const extraButton = panelItem.primaryButton!;
  extraButton.click();
  await waitUntil(() => !!signal);
  assertEquals(
      signal, 'extra-button',
      'Expected signal name "extra-button". Got ' + signal);
  signal = null;

  // Check cancel signal from the panel from a click.
  const cancel = panelItem.secondaryButton!;
  cancel.click();
  await waitUntil(() => !!signal);
  assertEquals(
      signal, 'cancel', 'Expected signal name "cancel". Got ' + signal);

  done();
}

export function testFilesDisplayPanelErrorMarker() {
  // Get the host display panel container element.
  const displayPanel =
      document.querySelector<DisplayPanel>('#test-xf-display-panel')!;

  // Add a summary panel item to the display panel container.
  const summaryPanel = displayPanel.addPanelItem('testpanel');
  summaryPanel.panelType = PanelType.SUMMARY;

  // Confirm the error marker is not visible by default.
  const progressIndicator =
      summaryPanel.shadowRoot!.querySelector<CircularProgress>(
          'xf-circular-progress')!;
  const errorMarker =
      progressIndicator.shadowRoot!.querySelector<SVGCircleElement>(
          '.errormark')!;
  assertEquals(
      errorMarker.getAttribute('visibility'), 'hidden',
      'Summary panel error marker should default to hidden');

  // Confirm the error marker can be made visible through property setting on
  // the progress indicator.
  progressIndicator.errorMarkerVisibility = 'visible';
  assertEquals(
      errorMarker.getAttribute('visibility'), 'visible',
      'Summary panel error marker should be visible');

  // Confirm we can change visibility of the error marker from panel item
  // property setting.
  summaryPanel.errorMarkerVisibility = 'hidden';
  assertEquals(
      errorMarker.getAttribute('visibility'), 'hidden',
      'Summary panel error marker should be hidden');

  // Confirm the panel item reflects the visibility of the error marker.
  assertEquals(
      summaryPanel.errorMarkerVisibility, 'hidden',
      'Summary panel error marker property is wrong, should be "hidden"');
}

export function testFilesDisplayPanelMixedSummary() {
  // Get the host display panel container element.
  const displayPanel =
      document.querySelector<DisplayPanel>('#test-xf-display-panel')!;

  // Add an error panel item to the display panel container.
  let errorPanel = displayPanel.addPanelItem('testpanel1');
  errorPanel.panelType = PanelType.ERROR;
  assertEquals('status', errorPanel.indicator);

  // Add a progress panel item to the display panel container.
  const progressPanel = displayPanel.addPanelItem('testpanel2');
  progressPanel.panelType = PanelType.PROGRESS;

  // Verify a summary panel item is created and shows the error indicator.
  const summaryContainer =
      displayPanel.shadowRoot!.querySelector<HTMLDivElement>('#summary')!;
  let summaryPanelItem =
      summaryContainer.querySelector<PanelItem>('xf-panel-item')!;
  assertEquals(PanelType.SUMMARY, summaryPanelItem.panelType);
  assertEquals('largeprogress', summaryPanelItem.indicator);
  assertEquals('visible', summaryPanelItem.errorMarkerVisibility);

  // Remove the error panel item and add a second progress panel item.
  displayPanel.removePanelItem(errorPanel);

  const extraProgressPanel = displayPanel.addPanelItem('testpanel3');
  extraProgressPanel.panelType = PanelType.PROGRESS;

  // Verify a summary panel item is created without an error indicator.
  summaryPanelItem =
      summaryContainer.querySelector<PanelItem>('xf-panel-item')!;
  assertEquals(PanelType.SUMMARY, summaryPanelItem.panelType);
  assertEquals('largeprogress', summaryPanelItem.indicator);
  assertEquals('hidden', summaryPanelItem.errorMarkerVisibility);

  // Remove the progress panels and add two info (a.k.a. warning) panel items.
  displayPanel.removeAllPanelItems();

  const infoPanel = displayPanel.addPanelItem('testpanel4');
  infoPanel.panelType = PanelType.INFO;

  const extraInfoPanel = displayPanel.addPanelItem('testpanel5');
  extraInfoPanel.panelType = PanelType.INFO;

  // Verify a summary panel item is created with a warning indicator.
  summaryPanelItem =
      summaryContainer.querySelector<PanelItem>('xf-panel-item')!;
  assertEquals(PanelType.SUMMARY, summaryPanelItem.panelType);
  assertEquals('status', summaryPanelItem.indicator);
  assertEquals('warning', summaryPanelItem.status);

  // Remove one info panel and add 2 error panel items.
  displayPanel.removePanelItem(extraInfoPanel);

  errorPanel = displayPanel.addPanelItem('testpanel6');
  errorPanel.panelType = PanelType.ERROR;

  const extraErrorPanel = displayPanel.addPanelItem('testpanel7');
  extraErrorPanel.panelType = PanelType.ERROR;

  // Verify a summary panel item is shown, with an error status indicator.
  summaryPanelItem =
      summaryContainer.querySelector<PanelItem>('xf-panel-item')!;
  assertEquals(PanelType.SUMMARY, summaryPanelItem.panelType);
  assertEquals('status', summaryPanelItem.indicator);
  assertEquals('failure', summaryPanelItem.status);

  // Remove the error panels items and add a done (a.k.a. success) panel item.
  displayPanel.removePanelItem(errorPanel);
  displayPanel.removePanelItem(extraErrorPanel);

  const donePanel = displayPanel.addPanelItem('testpanel8');
  donePanel.panelType = PanelType.DONE;

  // Verify a summary panel item is created with a warning indicator.
  summaryPanelItem =
      summaryContainer.querySelector<PanelItem>('xf-panel-item')!;
  assertEquals(PanelType.SUMMARY, summaryPanelItem.panelType);
  assertEquals('status', summaryPanelItem.indicator);
  assertEquals('warning', summaryPanelItem.status);

  // Remove the info panel items and add another done panel item.
  displayPanel.removePanelItem(infoPanel);

  const extraDonePanel = displayPanel.addPanelItem('testpanel9');
  extraDonePanel.panelType = PanelType.DONE;

  // Verify a summary panel is shown with success indicator.
  summaryPanelItem =
      summaryContainer.querySelector<PanelItem>('xf-panel-item')!;
  assertEquals(PanelType.SUMMARY, summaryPanelItem.panelType);
  assertEquals('status', summaryPanelItem.indicator);
  assertEquals('success', summaryPanelItem.status);
}

export async function testFilesDisplayPanelMixedProgress() {
  // Get the host display panel container element.
  const displayPanel =
      document.querySelector<DisplayPanel>('#test-xf-display-panel')!;

  // Add a generic progress panel item to the display panel container.
  const progressPanel = displayPanel.addPanelItem('testpanel1');
  progressPanel.panelType = PanelType.PROGRESS;
  progressPanel.progress = '1';

  // Add a format progress panel item to the display panel container.
  const formatProgressPanel = displayPanel.addPanelItem('testpanel2');
  formatProgressPanel.panelType = PanelType.FORMAT_PROGRESS;
  formatProgressPanel.progress = '2';

  // Confirm that format progress panels do not have a cancel button.
  assertEquals(null, formatProgressPanel.secondaryButton);

  // Add a drive sync progress panel item to the display panel container.

  const syncProgressPanel = displayPanel.addPanelItem('testpanel3');
  syncProgressPanel.panelType = PanelType.SYNC_PROGRESS;
  syncProgressPanel.progress = '6';

  // Confirm that sync progress panels do not have a cancel button.
  assertEquals(null, syncProgressPanel.secondaryButton);

  // Verify a summary panel item is created with the correct average.
  const summaryContainer =
      displayPanel.shadowRoot!.querySelector<HTMLDivElement>('#summary')!;
  const summaryPanelItem =
      summaryContainer.querySelector<PanelItem>('xf-panel-item')!;
  assertEquals(PanelType.SUMMARY, summaryPanelItem.panelType);
  assertEquals('largeprogress', summaryPanelItem.indicator);
  assertEquals('hidden', summaryPanelItem.errorMarkerVisibility);
  assertEquals(3, summaryPanelItem.progress);
}

export function testFilesDisplayPanelCircularProgress() {
  // Get the host display panel container element.
  const displayPanel =
      document.querySelector<DisplayPanel>('#test-xf-display-panel')!;

  // Add a progress panel item to the display panel container.
  const progressPanel = displayPanel.addPanelItem('testpanel1');
  progressPanel.panelType = PanelType.PROGRESS;

  // Verify the circular progress panel item marker stroke width.
  const circularProgress =
      progressPanel.shadowRoot!.querySelector<CircularProgress>('#indicator')!;
  const strokeWidthContainerGroup =
      circularProgress.shadowRoot!.querySelector<SVGGElement>('#circles')!;
  assertEquals('3', strokeWidthContainerGroup.getAttribute('stroke-width'));

  // Verify setting large radius on the circular marker changes stroke width.
  circularProgress.setAttribute('radius', '11');
  assertEquals('4', strokeWidthContainerGroup.getAttribute('stroke-width'));
}

// TODO(b/293228531): Reenable test when fixed for createElement().
export async function disabledTestFilesDisplayPanelSummaryPanel(
    done: VoidCallback) {
  // Get the host display panel container element.
  const displayPanel =
      document.querySelector<DisplayPanel>('#test-xf-display-panel')!;

  // Declare the expected panel item height managed from CSS.
  const singlePanelHeight = 68;

  // Add a progress panel item to the display panel container.
  let progressPanel = displayPanel.addPanelItem('testpanel1');
  progressPanel.panelType = PanelType.PROGRESS;

  // Confirm the expected height of a single panelItem.
  let bounds = progressPanel.getBoundingClientRect();
  assert(bounds.height === singlePanelHeight);

  // Add second panel item.
  progressPanel = displayPanel.addPanelItem('testpanel2');
  progressPanel.panelType = PanelType.PROGRESS;

  // Confirm multiple progress panel items are hidden by default.
  const panelContainer =
      displayPanel.shadowRoot!.querySelector<HTMLDivElement>('#panels')!;
  assertTrue(panelContainer.hasAttribute('hidden'));

  // Confirm multiple progress panels cause creation of a summary panel.
  const summaryContainer =
      displayPanel.shadowRoot!.querySelector<HTMLDivElement>('#summary')!;
  let summaryPanelItem =
      summaryContainer.querySelector<PanelItem>('xf-panel-item')!;
  assertEquals(summaryPanelItem.panelType, PanelType.SUMMARY);

  // Confirm the expected height of the summary panel.
  bounds = summaryPanelItem.getBoundingClientRect();
  assert(bounds.height === singlePanelHeight);

  // Trigger expand of the summary panel.
  const expandButton = summaryPanelItem.shadowRoot!.querySelector<PanelButton>(
      '#primary-action')!;
  expandButton.click();

  // Confirm the panel container is no longer hidden.
  assertFalse(panelContainer.hasAttribute('hidden'));

  // Remove a progress panel and ensure the summary panel is removed.
  const panelToRemove = displayPanel.findPanelItemById('testpanel1')!;
  displayPanel.removePanelItem(panelToRemove);
  summaryPanelItem =
      summaryContainer.querySelector<PanelItem>('xf-panel-item')!;
  assertEquals(summaryPanelItem, null);

  // Confirm the reference to the removed panel item is gone.
  assertEquals(displayPanel.findPanelItemById('testpanel1'), null);

  // Add another panel item and confirm the expanded state persists by
  // checking the panel container is not hidden and there is a summary panel.
  progressPanel = displayPanel.addPanelItem('testpanel1');
  progressPanel.panelType = PanelType.PROGRESS;
  assertFalse(panelContainer.hasAttribute('hidden'));
  summaryPanelItem =
      summaryContainer.querySelector<PanelItem>('xf-panel-item')!;
  assertEquals(summaryPanelItem.panelType, PanelType.SUMMARY);

  done();
}

export async function testFilesDisplayPanelTransferDetails() {
  // Get the host display panel container element.
  const displayPanel =
      document.querySelector<DisplayPanel>('#test-xf-display-panel')!;

  // Add a generic progress panel item to the display panel container.
  const progressPanel = displayPanel.addPanelItem('testpanel1');
  progressPanel.panelType = PanelType.PROGRESS;

  // Check detailed-panel is added when FilesTransferDetails enabled.
  assertEquals('detailed-panel', progressPanel.getAttribute('detailed-panel'));
}

export function testFilesDisplayPanelTransferDetailsSummary(
    done: VoidCallback) {
  // Get the host display panel container element.
  const displayPanel =
      document.querySelector<DisplayPanel>('#test-xf-display-panel')!;

  // Add two generic progress panel items to the display panel container.
  const panel1 = displayPanel.addPanelItem('testpanel1');
  panel1.panelType = PanelType.PROGRESS;

  const panel2 = displayPanel.addPanelItem('testpanel2');
  panel2.panelType = PanelType.PROGRESS;

  const panelContainer =
      displayPanel.shadowRoot!.querySelector<HTMLDivElement>('#panels')!;
  assertTrue(panelContainer.hasAttribute('hidden'));

  const summaryContainer =
      displayPanel.shadowRoot!.querySelector<HTMLDivElement>('#summary')!;
  const summaryPanelItem =
      summaryContainer.querySelector<HTMLDivElement>('#summary-panel')!;

  // Check summary panel has both detailed-panel and detailed-summary attribute.
  assertEquals(
      'detailed-panel', summaryPanelItem.getAttribute('detailed-panel'));
  assertEquals('', summaryPanelItem.getAttribute('detailed-summary'));

  // Trigger expand of the summary panel by summary label.
  const summaryLabel =
      summaryPanelItem.shadowRoot!.querySelector<HTMLDivElement>(
          '.xf-panel-text')!;
  summaryLabel.click();

  // Confirm the panel container is no longer hidden.
  assertFalse(panelContainer.hasAttribute('hidden'));
  assertEquals('expanded', summaryPanelItem.getAttribute('data-category'));

  done();
}

/**
 * Tests that the extra-button appears when the value is in the dataset and
 * sends the appropriate signal on click.
 */
export async function testExtraButtonCanBeAddedAndRespondsToAction(
    done: VoidCallback) {
  // Get the host display panel container element.
  const displayPanel =
      document.querySelector<DisplayPanel>('#test-xf-display-panel')!;

  const panelItem = displayPanel.addPanelItem('testpanel');
  panelItem.dataset['extraButtonText'] = 'Extra button';
  panelItem.panelType = PanelType.DONE;

  // Setup the panel item signal (click) callback.
  let signal: string|null = null;
  panelItem.signalCallback = (name) => {
    assert(typeof name === 'string');
    signal = name;
  };

  const extraButton = panelItem.primaryButton!;
  extraButton.click();
  await waitUntil(() => !!signal);
  assertEquals(
      signal, 'extra-button',
      'Expected signal name "extra-button". Got ' + signal);
  signal = null;

  // Check dismiss signal from the panel from a click.
  const dismiss = panelItem.secondaryButton!;
  dismiss.click();
  await waitUntil(() => !!signal);
  assertEquals(
      signal, 'dismiss', 'Expected signal name "dismiss". Got ' + signal);

  done();
}