chromium/chrome/test/data/webui/chromeos/settings/controls/v2/pref_control_mixin_internal_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.

import {CrSettingsPrefs, PrefControlMixinInternal} from 'chrome://os-settings/os_settings.js';
import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {assertEquals, assertFalse, assertThrows, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
import {eventToPromise} from 'chrome://webui-test/test_util.js';

import {clearBody} from '../../utils.js';

const TestElementBase = PrefControlMixinInternal(PolymerElement);
class TestElement extends TestElementBase {}
customElements.define('test-element', TestElement);

suite('PrefControlMixinInternal', () => {
  let testElement: TestElement;

  const fakePrefObject = {
    key: 'foo.bar.baz',
    type: chrome.settingsPrivate.PrefType.STRING,
    value: 'initialValue',
  };

  setup(async () => {
    clearBody();
    testElement = document.createElement('test-element') as TestElement;
    testElement.id = 'exampleID';
    document.body.appendChild(testElement);
    await flushTasks();
  });

  teardown(() => {
    CrSettingsPrefs.resetForTesting();
  });

  suite('isPrefEnforced property', () => {
    test('is false if no pref provided', () => {
      assertFalse(testElement.isPrefEnforced);
    });

    test('is false if pref is provided but not enforced', () => {
      testElement.pref = {...fakePrefObject};
      assertFalse(testElement.isPrefEnforced);
    });

    [{
      enforcement: chrome.settingsPrivate.Enforcement.ENFORCED,
      isPrefEnforced: true,
    },
     {
       enforcement: chrome.settingsPrivate.Enforcement.RECOMMENDED,
       isPrefEnforced: false,
     },
     {
       enforcement: chrome.settingsPrivate.Enforcement.PARENT_SUPERVISED,
       isPrefEnforced: false,
     },
    ].forEach(({enforcement, isPrefEnforced}) => {
      test(`is ${isPrefEnforced} for pref enforcement: ${enforcement}`, () => {
        testElement.pref = {...fakePrefObject, enforcement};
        assertEquals(isPrefEnforced, testElement.isPrefEnforced);
      });
    });
  });

  suite('disabled property', () => {
    test('should reflect to attribute', () => {
      // `disabled` is false by default.
      assertFalse(testElement.hasAttribute('disabled'));

      testElement.disabled = true;
      assertTrue(testElement.hasAttribute('disabled'));

      testElement.disabled = false;
      assertFalse(testElement.hasAttribute('disabled'));
    });

    test('considers pref enforcement', () => {
      testElement.pref = {...fakePrefObject};
      assertFalse(testElement.disabled);

      testElement.pref = {
        ...fakePrefObject,
        enforcement: chrome.settingsPrivate.Enforcement.ENFORCED,
      };
      assertTrue(testElement.disabled);
    });

    test('cannot be overridden if pref is enforced', () => {
      testElement.pref = {
        ...fakePrefObject,
        enforcement: chrome.settingsPrivate.Enforcement.ENFORCED,
      };
      assertTrue(testElement.disabled);

      // Attempt to force enable the element. Element should still be disabled
      // since the pref is enforced.
      testElement.disabled = false;
      assertTrue(testElement.disabled);
    });
  });

  suite('validatePref()', () => {
    test('pref is not a string', () => {
      // Simulate a string value instead of a PrefObject. Use Object.assign() to
      // bypass typechecking here since there is no typechecking in Polymer HTML
      // data-binding.
      Object.assign(testElement, {pref: 'foobar'});

      assertThrows(() => {
        testElement.validatePref();
      }, 'TEST-ELEMENT#exampleID error: Invalid string literal.');
    });

    test('pref type is invalidated', () => {
      testElement.validPrefTypes = [chrome.settingsPrivate.PrefType.NUMBER];
      testElement.pref = {...fakePrefObject};

      assertThrows(() => {
        testElement.validatePref();
      }, 'TEST-ELEMENT#exampleID error: Invalid pref type STRING.');
    });

    test('pref type is validated', () => {
      testElement.validPrefTypes = [chrome.settingsPrivate.PrefType.STRING];
      testElement.pref = {...fakePrefObject};

      testElement.validatePref();
    });

    test('called once prefs are initialized', async () => {
      let validatePrefCalled = false;
      testElement['validatePref'] = () => {
        validatePrefCalled = true;
      };

      CrSettingsPrefs.setInitialized();
      await flushTasks();
      assertTrue(validatePrefCalled);
    });
  });

  suite('updatePrefValueFromUserAction()', () => {
    test('Raises an error if called when pref is not defined', async () => {
      assertThrows(() => {
        testElement.updatePrefValueFromUserAction('newValue9001');
      }, 'updatePrefValueFromUserAction() requires pref to be defined.');
    });

    test('Dispatches a "user-action-setting-pref-change" event', async () => {
      testElement.pref = {...fakePrefObject};

      const expectedValue = 'newValue9001';
      const eventPromise =
          eventToPromise('user-action-setting-pref-change', window);
      testElement.updatePrefValueFromUserAction(expectedValue);

      const event = await eventPromise;
      assertEquals(fakePrefObject.key, event.detail.prefKey);
      assertEquals(expectedValue, event.detail.value);
    });

    test('Does not update the pref object value directly', async () => {
      testElement.pref = {...fakePrefObject};
      const initialValue = testElement.pref.value;

      const eventPromise =
          eventToPromise('user-action-setting-pref-change', window);
      testElement.updatePrefValueFromUserAction('newValue9001');
      await eventPromise;
      assertEquals(initialValue, testElement.pref.value);
    });
  });
});