chromium/chrome/test/data/webui/settings/recent_site_permissions_test.ts

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

// clang-format off
import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import type {SettingsRecentSitePermissionsElement} from 'chrome://settings/lazy_load.js';
import {ContentSetting, ContentSettingsTypes, SiteSettingSource, SiteSettingsPrefsBrowserProxyImpl} from 'chrome://settings/lazy_load.js';
import {Router, routes} from 'chrome://settings/settings.js';
import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {isChildVisible, isVisible} from 'chrome://webui-test/test_util.js';
import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';

import {TestSiteSettingsPrefsBrowserProxy} from './test_site_settings_prefs_browser_proxy.js';
import {createRawSiteException} from './test_util.js';

// clang-format on

suite('CrSettingsRecentSitePermissionsTest', function() {
  /**
   * The mock proxy object to use during test.
   */
  let browserProxy: TestSiteSettingsPrefsBrowserProxy;

  let testElement: SettingsRecentSitePermissionsElement;

  setup(function() {
    browserProxy = new TestSiteSettingsPrefsBrowserProxy();
    SiteSettingsPrefsBrowserProxyImpl.setInstance(browserProxy);

    document.body.innerHTML = window.trustedTypes!.emptyHTML;
    testElement = document.createElement('settings-recent-site-permissions');
    document.body.appendChild(testElement);
    flush();
  });

  teardown(function() {
    testElement.remove();
    Router.getInstance().navigateTo(routes.BASIC);
  });

  test('No recent permissions', async function() {
    browserProxy.setRecentSitePermissions([]);
    Router.getInstance().navigateTo(routes.SITE_SETTINGS);
    await browserProxy.whenCalled('getRecentSitePermissions');
    flush();
    assertTrue(isChildVisible(testElement, '#noPermissionsText'));
  });

  test('Content setting strings', async function() {
    // Ensure no errors are generated for recent permissions for any content
    // settings type. Any JS errors are treated as a test failure, so no
    // explicit assertions are included.
    const origin = 'https://bar.com';
    for (const contentSettingType of Object.values(ContentSettingsTypes)) {
      if (contentSettingType === ContentSettingsTypes.STORAGE_ACCESS ||
          contentSettingType ===
              ContentSettingsTypes.TOP_LEVEL_STORAGE_ACCESS) {
        // Skip permission types that are not single origin; in the actual
        // implementation, getRecentSitePermissions only lists single origin
        // permissions.
        continue;
      }
      Router.getInstance().navigateTo(routes.BASIC);
      await flushTasks();
      const mockData = [{
        origin,
        displayName: 'bar.com',
        incognito: false,
        recentPermissions: [createRawSiteException(origin, {
          setting: ContentSetting.BLOCK,
          type: contentSettingType,
        })],
      }];
      browserProxy.setRecentSitePermissions(mockData);
      Router.getInstance().navigateTo(routes.SITE_SETTINGS);
      await browserProxy.whenCalled('getRecentSitePermissions');
      browserProxy.reset();
    }
  });

  test('Various recent permissions', async function() {
    const scheme = 'https://';
    const host1 = 'bar.com';
    const host2 = 'foo.com';
    const origin1 = `${scheme}${host1}`;
    const origin2 = `${scheme}${host2}`;
    const mockData = [
      {
        origin: origin1,
        displayName: host1,
        incognito: true,
        recentPermissions: [
          createRawSiteException(origin1, {
            setting: ContentSetting.BLOCK,
            type: ContentSettingsTypes.GEOLOCATION,
          }),
          createRawSiteException(origin1, {
            setting: ContentSetting.BLOCK,
            type: ContentSettingsTypes.NOTIFICATIONS,
          }),
          createRawSiteException(origin1, {
            setting: ContentSetting.BLOCK,
            type: ContentSettingsTypes.MIC,
          }),
          createRawSiteException(origin1, {
            setting: ContentSetting.ALLOW,
            type: ContentSettingsTypes.CAMERA,
          }),
          createRawSiteException(origin1, {
            setting: ContentSetting.ALLOW,
            type: ContentSettingsTypes.ADS,
          }),
          createRawSiteException(origin1, {
            setting: ContentSetting.BLOCK,
            source: SiteSettingSource.EMBARGO,
            type: ContentSettingsTypes.MIDI_DEVICES,
          }),
        ],
      },
      {
        origin: origin2,
        displayName: host2,
        incognito: false,
        recentPermissions: [
          createRawSiteException(origin2, {
            setting: ContentSetting.BLOCK,
            type: ContentSettingsTypes.POPUPS,
          }),
          createRawSiteException(origin2, {
            setting: ContentSetting.BLOCK,
            source: SiteSettingSource.EMBARGO,
            type: ContentSettingsTypes.CLIPBOARD,
          }),
        ],
      },
    ];
    browserProxy.setRecentSitePermissions(mockData);
    Router.getInstance().navigateTo(routes.SITE_SETTINGS);
    await browserProxy.whenCalled('getRecentSitePermissions');
    flush();

    assertFalse(testElement.noRecentPermissions);
    assertFalse(isChildVisible(testElement, '#noPermissionsText'));

    const siteEntries =
        testElement.shadowRoot!.querySelectorAll('.link-button');
    assertEquals(2, siteEntries.length);

    assertEquals(
        host1,
        siteEntries[0]!.querySelector(
                           '.url-directionality')!.textContent!.trim());
    assertEquals(
        host2,
        siteEntries[1]!.querySelector(
                           '.url-directionality')!.textContent!.trim());

    const incognitoIcons =
        testElement.shadowRoot!.querySelectorAll<HTMLElement>(
            '.incognito-icon');
    assertTrue(isVisible(incognitoIcons[0]!));
    assertFalse(isVisible(incognitoIcons[1]!));

    // Check that the text describing the changed permissions is correct.
    const i18n = testElement.i18n.bind(testElement);

    let allowed = i18n(
        'recentPermissionAllowedTwoItems',
        i18n('siteSettingsCameraMidSentence'),
        i18n('siteSettingsAdsMidSentence'));
    const autoBlocked = i18n(
        'recentPermissionAutoBlockedOneItem',
        i18n('siteSettingsMidiDevicesMidSentence'));
    let blocked = i18n(
        'recentPermissionBlockedMoreThanTwoItems',
        i18n('siteSettingsLocationMidSentence'), 2);

    const expectedPermissionString1 = `${allowed}${i18n('sentenceEnd')} ${
        autoBlocked}${i18n('sentenceEnd')} ${blocked}${i18n('sentenceEnd')}`;

    allowed = i18n(
        'recentPermissionAutoBlockedOneItem',
        i18n('siteSettingsClipboardMidSentence'));
    blocked = i18n(
        'recentPermissionBlockedOneItem',
        i18n('siteSettingsPopupsMidSentence'));

    const expectedPermissionString3 =
        `${allowed}${i18n('sentenceEnd')} ${blocked}${i18n('sentenceEnd')}`;

    assertEquals(
        expectedPermissionString1,
        siteEntries[0]!.querySelector('.second-line')!.textContent!.trim());
    assertEquals(
        expectedPermissionString3,
        siteEntries[1]!.querySelector('.second-line')!.textContent!.trim());
  });
});