function startObserverTest(initiallyEnabled, initiallyDisabled) {
  if (observerTestState) {
    chrome.test.notifyFail('Initializing observe features test before the ' +
                           'previous one finished');
    return;
  }

  observerTestState = {
    toBeDisabled: [],
    toBeEnabled: []
  };

  /**
   * Finds feature with the provided name in the.
   * @param {Array<{name: string, listener: function(Event)>} list The list in
   *     which to search.
   * @param {string} featureName The feature name for which to search.
   * @return {number} The feature's index in the list. If not found returns -1.
   */
  function findFeatureIndex(list, featureName) {
    for (var i = 0; i < list.length; ++i)
      if (list[i].name == featureName)
        return i;
    return -1;
  }

  /**
   * Initializes listener for a feature and adds it to the appropriate list in
   * {@code observerTestState}.
   * @param {string} feature The feature name.
   * @param {boolean} initiallyEnabled Whether the feature is initially enabled.
   */
  function initTestParamsForFeature(feature, initiallyEnabled) {
    var list = initiallyEnabled ? observerTestState.toBeDisabled :
                                  observerTestState.toBeEnabled;

    var listener = function(ev) {
      // Fail the test in case the new feature value is not as expected, but
      // before that, do some cleanup.
      if (initiallyEnabled == ev.value)
        clearRemainingListeners();
      chrome.test.assertEq(!initiallyEnabled, ev.value);

      var index = findFeatureIndex(list, feature);
      if (index < 0)
        clearRemaningListeners();
      chrome.test.assertTrue(index > -1);

      chrome.accessibilityFeatures[feature].onChange.removeListener(
          list[index].listener);
      list.splice(index, 1);

      if (observerTestState.toBeEnabled.length == 0 &&
          observerTestState.toBeDisabled.length == 0) {
        chrome.test.succeed();
      }
    }

    list.push({name: feature, listener: listener});
    chrome.accessibilityFeatures[feature].onChange.addListener(listener);
  }

  /**
   * If any features are still being disabled, removes their listeners.
   * This situation may happen when test fails.
   */
  function clearRemainingListeners() {
    observerTestState.toBeEnabled.forEach(function(feature) {
      chrome.accessibilityFeatures[feature.name].onChange.removeListener(
          feature.listener);
      feature.listener = null;
    });
    observerTestState.toBeDisabled.forEach(function(feature) {
      chrome.accessibilityFeatures[feature.name].onChange.removeListener(
          feature.listener);
      feature.listener = null;
    });
  }

  initiallyEnabled.forEach(function(feature) {
    initTestParamsForFeature(feature, true);
  });

  initiallyDisabled.forEach(function(feature) {
    initTestParamsForFeature(feature, false);
  });

  // Send success, so the Chrome side of the test continues. The test is not
  // actually over yet, and is expected to send another success notification
  // when all featureChanged events are seen.
  chrome.test.succeed();
}
/**
 * Initializes and starts the test that observes that {@code onChange} event is
 * triggered when a feature status changes. The features are actually changed in
 * Chrome side of the test. During a single test, two success notification will
 * be sent (if the test succeeds): once when the features' change listeners have
 * been setup, and the second time when all the expected events are seen.
 * In case of the failure notification, no further notifications will be sent.
 * @param {Array<string>} initiallyEnabled
 *     The list of features that are enabled at the start of the test, and for
 *     which a {@code onChange} event with value false should be observed.
 * @param {Array<string>} initiallyDisabled
 *     The list of features that are disabled at the start of the test, and for
 *     which a {@code onChange} event with value true should be observed.
 */
Initializes and starts the test that observes that  onChange event is
triggered when a feature status changes. The features are actually changed in
Chrome side of the test. During a single test, two success notification will
be sent (if the test succeeds): once when the features' change listeners have
been setup, and the second time when all the expected events are seen.
In case of the failure notification, no further notifications will be sent.
@param {Array} initiallyEnabled
The list of features that are enabled at the start of the test, and for
which a  onChange event with value false should be observed.
@param {Array} initiallyDisabled
The list of features that are disabled at the start of the test, and for
which a  onChange event with value true should be observed.
Initializes and starts the test that observes that onChange event is triggered when a feature status changes . The features are actually changed in Chrome side of the test . During a single test two success notification will be sent ( if the test succeeds ) : once when the features ' change listeners have been setup and the second time when all the expected events are seen . In case of the failure notification no further notifications will be sent . @param { Array } initiallyEnabled The list of features that are enabled at the start of the test and for which a onChange event with value false should be observed . @param { Array } initiallyDisabled The list of features that are disabled at the start of the test and for which a onChange event with value true should be observed .
function startObserverTest(initiallyEnabled, initiallyDisabled) {
  if (observerTestState) {
    chrome.test.notifyFail('Initializing observe features test before the ' +
                           'previous one finished');
    return;
  }
  observerTestState = {
    toBeDisabled: [],
    toBeEnabled: []
  };
  function findFeatureIndex(list, featureName) {
    for (var i = 0; i < list.length; ++i)
      if (list[i].name == featureName)
        return i;
    return -1;
  }
  function initTestParamsForFeature(feature, initiallyEnabled) {
    var list = initiallyEnabled ? observerTestState.toBeDisabled :
                                  observerTestState.toBeEnabled;
    var listener = function(ev) {
      if (initiallyEnabled == ev.value)
        clearRemainingListeners();
      chrome.test.assertEq(!initiallyEnabled, ev.value);
      var index = findFeatureIndex(list, feature);
      if (index < 0)
        clearRemaningListeners();
      chrome.test.assertTrue(index > -1);
      chrome.accessibilityFeatures[feature].onChange.removeListener(
          list[index].listener);
      list.splice(index, 1);
      if (observerTestState.toBeEnabled.length == 0 &&
          observerTestState.toBeDisabled.length == 0) {
        chrome.test.succeed();
      }
    }
    list.push({name: feature, listener: listener});
    chrome.accessibilityFeatures[feature].onChange.addListener(listener);
  }
  function clearRemainingListeners() {
    observerTestState.toBeEnabled.forEach(function(feature) {
      chrome.accessibilityFeatures[feature.name].onChange.removeListener(
          feature.listener);
      feature.listener = null;
    });
    observerTestState.toBeDisabled.forEach(function(feature) {
      chrome.accessibilityFeatures[feature.name].onChange.removeListener(
          feature.listener);
      feature.listener = null;
    });
  }
  initiallyEnabled.forEach(function(feature) {
    initTestParamsForFeature(feature, true);
  });
  initiallyDisabled.forEach(function(feature) {
    initTestParamsForFeature(feature, false);
  });
  chrome.test.succeed();
}
function startObserverTest ( initiallyEnabled , initiallyDisabled ) { if ( observerTestState ) { chrome . test . notifyFail ( 'Initializing observe features test before the ' + 'previous one finished' ) ; return ; } observerTestState = { toBeDisabled : [ ] , toBeEnabled : [ ] } ; function findFeatureIndex ( list , featureName ) { for ( var i = 0 ; i < list . length ; ++ i ) if ( list [ i ] . name == featureName ) return i ; return - 1 ; } function initTestParamsForFeature ( feature , initiallyEnabled ) { var list = initiallyEnabled ? observerTestState . toBeDisabled : observerTestState . toBeEnabled ; var listener = function ( ev ) { if ( initiallyEnabled == ev . value ) clearRemainingListeners ( ) ; chrome . test . assertEq ( ! initiallyEnabled , ev . value ) ; var index = findFeatureIndex ( list , feature ) ; if ( index < 0 ) clearRemaningListeners ( ) ; chrome . test . assertTrue ( index > - 1 ) ; chrome . accessibilityFeatures [ feature ] . onChange . removeListener ( list [ index ] . listener ) ; list . splice ( index , 1 ) ; if ( observerTestState . toBeEnabled . length == 0 && observerTestState . toBeDisabled . length == 0 ) { chrome . test . succeed ( ) ; } } list . push ( { name : feature , listener : listener } ) ; chrome . accessibilityFeatures [ feature ] . onChange . addListener ( listener ) ; } function clearRemainingListeners ( ) { observerTestState . toBeEnabled . forEach ( function ( feature ) { chrome . accessibilityFeatures [ feature . name ] . onChange . removeListener ( feature . listener ) ; feature . listener = null ; } ) ; observerTestState . toBeDisabled . forEach ( function ( feature ) { chrome . accessibilityFeatures [ feature . name ] . onChange . removeListener ( feature . listener ) ; feature . listener = null ; } ) ; } initiallyEnabled . forEach ( function ( feature ) { initTestParamsForFeature ( feature , true ) ; } ) ; initiallyDisabled . forEach ( function ( feature ) { initTestParamsForFeature ( feature , false ) ; } ) ; chrome . test . succeed ( ) ; }
Initializes and starts the test that observes that {@code onChange} event is
 triggered when a feature status changes.
Initializes and starts the test that observes that { @code onChange } event is triggered when a feature status changes .
/**
   * Finds feature with the provided name in the.
   * @param {Array<{name: string, listener: function(Event)>} list The list in
   *     which to search.
   * @param {string} featureName The feature name for which to search.
   * @return {number} The feature's index in the list. If not found returns -1.
   */ /**
   * Initializes listener for a feature and adds it to the appropriate list in
   * {@code observerTestState}.
   * @param {string} feature The feature name.
   * @param {boolean} initiallyEnabled Whether the feature is initially enabled.
   */ // Fail the test in case the new feature value is not as expected, but // before that, do some cleanup. /**
   * If any features are still being disabled, removes their listeners.
   * This situation may happen when test fails.
   */ // Send success, so the Chrome side of the test continues. The test is not // actually over yet, and is expected to send another success notification // when all featureChanged events are seen.