text: /*! @license
   * Shaka Player
   * Copyright 2016 Google LLC
   * SPDX-License-Identifier: Apache-2.0
   */
  
  describe('Demo', () => {
    beforeEach(() => {
      // Make mock versions of misc third-party libraries.
      window['tippy'] = () => {};
      window['Awesomplete'] = class {
        constructor() {
          this.list = [];
          this.minChars = 0;
        }
  
        evaluate() {}
      };
      window['componentHandler'] = class {
        upgradeDom() {}
      };
      window['dialogPolyfill'] = {registerDialog: (dialog) => {}};
  
      // Make the FakeDemoMain, which will trigger the various tabs to load.
      shaka.test.FakeDemoMain.setup();
    });
  
    afterEach(async () => {
      delete window['tippy'];
      delete window['Awesomplete'];
      delete window['componentHandler'];
      delete window['dialogPolyfill'];
      await shakaDemoMain.cleanup();
    });
  
    it('has all messages defined', async () => {
      const englishBuffer =
          await shaka.test.Util.fetch('/base/demo/locales/en.json');
      const englishMessages = JSON.parse(shaka.util.StringUtils.fromUTF8(
          englishBuffer));
      const sourceBuffer =
          await shaka.test.Util.fetch('/base/demo/locales/source.json');
      const sourceMessages = JSON.parse(shaka.util.StringUtils.fromUTF8(
          sourceBuffer));
  
      for (const id of Object.values(shakaDemo.MessageIds)) {
        expect(englishMessages[id]).withContext(`id=${id}, English`).toBeTruthy();
        expect(sourceMessages[id]).withContext(`id=${id}, source`).toBeTruthy();
      }
    });
  
    describe('config', () => {
      it('does not have entries for invalid config options', () => {
        // We determine whether a config option has been made or not by looking at
        // which config values have been queried (via the fake main object's
        // |getCurrentConfigValue| method).
        const allConfigQueries = shakaDemoMain.getCurrentConfigValue.calls.all();
        const configQueryData = allConfigQueries.map((spyData) => {
          return spyData.args[0];
        });
  
        const knownValueNames = new Set();
        checkConfig((valueName) => {
          knownValueNames.add(valueName);
        });
        for (const valueName of configQueryData) {
          if (!knownValueNames.has(valueName)) {
            fail('Demo has a config field for unknown value "' + valueName + '"');
          }
        }
      });
  
      it('has an entry for every config option', () => {
        // We determine whether a config option has been made or not by looking at
        // which config values have been queried (via the fake main object's
        // |getCurrentConfigValue| method).
        const allConfigQueries = shakaDemoMain.getCurrentConfigValue.calls.all();
        const configQueryData = allConfigQueries.map((spyData) => {
          return spyData.args[0];
        });
  
        checkConfig((valueName) => {
          if (!configQueryData.includes(valueName)) {
            fail('Demo does not have a config field for "' + valueName + '"');
          }
        });
      });
  
      /** @param {function(string)} checkValueNameFn */
      function checkConfig(checkValueNameFn) {
        const configPrimitives = new Set(['number', 'string', 'boolean']);
        const exceptions = new Set()
            .add('preferredVariantRole')
            .add('playRangeStart')
            .add('playRangeEnd')
            .add('manifest.dash.keySystemsByURI')
            .add('manifest.hls.mediaPlaylistFullMimeType')
            .add('drm.keySystemsMapping');
  
        /**
         * @param {!Object} section
         * @param {string} accumulatedName
         */
        const check = (section, accumulatedName) => {
          for (const key in section) {
            const name = (accumulatedName) ? (accumulatedName + '.' + key) : key;
            const value = section[key];
  
            if (!exceptions.has(name)) {
              if (configPrimitives.has(typeof value)) {
                checkValueNameFn(name);
              } else {
                // It's a sub-section.
                check(value, name);
              }
            }
          }
        };
        check(shakaDemoMain.getConfiguration(), '');
      }
    });
  });
  