chromium/chrome/test/data/webui/cr_components/certificate_manager/certificate_manager_v2_focus_test.ts

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

// These test suites test the parts of certificate-manager v2 component that
// depend on what element is focused, and thus need to be an
// interactive_ui_test to avoid flake.

import 'chrome://resources/cr_components/certificate_manager/certificate_manager_v2.js';
import 'chrome://certificate-manager/strings.m.js';

import type {CertificateManagerV2Element} from 'chrome://resources/cr_components/certificate_manager/certificate_manager_v2.js';
import {CertificateSource} from 'chrome://resources/cr_components/certificate_manager/certificate_manager_v2.mojom-webui.js';
import {CertificatesV2BrowserProxy} from 'chrome://resources/cr_components/certificate_manager/certificates_v2_browser_proxy.js';
import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js';
import {getDeepActiveElement} from 'chrome://resources/js/util.js';
import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {microtasksFinished} from 'chrome://webui-test/test_util.js';

import {TestCertificateManagerProxy} from './certificate_manager_v2_test_support.js';

suite('CertificateManagerV2FocusTest', () => {
  let certManager: CertificateManagerV2Element;
  let testProxy: TestCertificateManagerProxy;

  setup(async () => {
    document.body.innerHTML = window.trustedTypes!.emptyHTML;
    await navigator.clipboard.writeText('');
    testProxy = new TestCertificateManagerProxy();
    CertificatesV2BrowserProxy.setInstance(testProxy);
  });

  function initializeElement() {
    certManager = document.createElement('certificate-manager-v2');
    document.body.appendChild(certManager);
  }

  test('Copy CRS hash', async () => {
    const getCertificatesResolver = new PromiseResolver<void>();
    testProxy.handler.setCertificatesCallback((source: CertificateSource) => {
      if (source === CertificateSource.kChromeRootStore) {
        getCertificatesResolver.resolve();
        return {
          certs: [
            {
              sha256hashHex: 'deadbeef',
              displayName: 'cert1',
            },
          ],
        };
      }
      return {certs: []};
    });
    initializeElement();

    await getCertificatesResolver.promise;
    await microtasksFinished();
    assertFalse(certManager.$.toast.open);

    const certEntries =
        certManager.$.crsCertSection.$.crsCerts.$.certs.querySelectorAll(
            'certificate-entry-v2');
    assertEquals(1, certEntries.length, 'no certs displayed');
    assertEquals('', await navigator.clipboard.readText());
    certEntries[0]!.$.copy.click();
    assertTrue(certManager.$.toast.open);
    assertEquals('deadbeef', await navigator.clipboard.readText());
  });

  test('Copy platform client certs hash', async () => {
    const getCertificatesResolver = new PromiseResolver<void>();
    testProxy.handler.setCertificatesCallback((source: CertificateSource) => {
      if (source === CertificateSource.kPlatformClientCert) {
        getCertificatesResolver.resolve();
        return {
          certs: [
            {
              sha256hashHex: 'deadbeef2',
              displayName: 'cert2',
            },
          ],
        };
      }
      return {certs: []};
    });
    initializeElement();
    certManager.$.clientMenuItem.click();
    certManager.$.viewOsImportedClientCerts.click();

    await getCertificatesResolver.promise;
    await microtasksFinished();
    assertFalse(certManager.$.toast.open);

    const certLists =
        certManager.$.platformClientCertsSection.shadowRoot!.querySelectorAll(
            'certificate-list-v2');
    assertEquals(1, certLists.length, 'no cert lists displayed');

    const certEntries =
        certLists[0]!.$.certs.querySelectorAll('certificate-entry-v2');
    assertEquals(1, certEntries.length, 'no certs displayed');

    assertEquals('', await navigator.clipboard.readText());
    certEntries[0]!.$.copy.click();
    assertTrue(certManager.$.toast.open);
    assertEquals('deadbeef2', await navigator.clipboard.readText());
  });

  // <if expr="is_win or is_macosx or is_linux">
  test('Copy provisioned client certs hash', async () => {
    const getCertificatesResolver = new PromiseResolver<void>();
    testProxy.handler.setCertificatesCallback((source: CertificateSource) => {
      if (source === CertificateSource.kProvisionedClientCert) {
        getCertificatesResolver.resolve();
        return {
          certs: [
            {
              sha256hashHex: 'deadbeef3',
              displayName: 'cert3',
            },
          ],
        };
      }
      return {certs: []};
    });

    initializeElement();
    await getCertificatesResolver.promise;
    await microtasksFinished();
    assertFalse(certManager.$.toast.open);

    const entries =
        certManager.$.provisionedClientCerts.$.certs.querySelectorAll(
            'certificate-entry-v2');
    assertEquals(1, entries.length, 'no certs displayed');

    assertEquals('', await navigator.clipboard.readText());
    entries[0]!.$.copy.click();
    assertTrue(certManager.$.toast.open);
    assertEquals('deadbeef3', await navigator.clipboard.readText());
  });
  // </if>

  // <if expr="is_chromeos">
  test('Copy extensions client certs hash', async () => {
    const getCertificatesResolver = new PromiseResolver<void>();
    testProxy.handler.setCertificatesCallback((source: CertificateSource) => {
      if (source === CertificateSource.kExtensionsClientCert) {
        getCertificatesResolver.resolve();
        return {
          certs: [
            {
              sha256hashHex: 'deadbeef4',
              displayName: 'cert4',
            },
          ],
        };
      }
      return {certs: []};
    });

    initializeElement();
    await getCertificatesResolver.promise;
    await microtasksFinished();
    assertFalse(certManager.$.toast.open);

    const entries =
        certManager.$.extensionsClientCerts.$.certs.querySelectorAll(
            'certificate-entry-v2');
    assertEquals(1, entries.length, 'no certs displayed');

    assertEquals('', await navigator.clipboard.readText());
    entries[0]!.$.copy.click();
    assertTrue(certManager.$.toast.open);
    assertEquals('deadbeef4', await navigator.clipboard.readText());
  });
  // </if>

  test('Check Focus when going in and out of subpages', async () => {
    initializeElement();
    await microtasksFinished();
    certManager.$.viewOsImportedCerts.click();
    await microtasksFinished();

    // Check focus is on back button in platform certs section.
    assertTrue(
        certManager.$.platformCertsSection.classList.contains('selected'));
    const elementInFocus = getDeepActiveElement();
    assertTrue(!!elementInFocus);
    assertEquals('backButton', elementInFocus.id);
    const subsection = (elementInFocus.getRootNode() as ShadowRoot).host;
    assertEquals('platformCertsSection', subsection.id);

    (elementInFocus as HTMLElement).click();
    await microtasksFinished();

    // Check focus is on link row going to platform certs section.
    assertTrue(certManager.$.localCertSection.classList.contains('selected'));
    const newElementInFocus = getDeepActiveElement();
    assertTrue(!!newElementInFocus);
    const linkRow = (newElementInFocus.getRootNode() as ShadowRoot).host;
    assertEquals('viewOsImportedCerts', linkRow.id);
  });
});