text: // Copyright 2008 The Closure Library Authors. All Rights Reserved.
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //      http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS-IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  goog.provide('goog.ui.ComboBoxTest');
  goog.setTestOnly('goog.ui.ComboBoxTest');
  
  goog.require('goog.dom');
  goog.require('goog.dom.TagName');
  goog.require('goog.dom.classlist');
  goog.require('goog.events.KeyCodes');
  goog.require('goog.testing.MockClock');
  goog.require('goog.testing.events');
  goog.require('goog.testing.jsunit');
  goog.require('goog.ui.ComboBox');
  goog.require('goog.ui.ComboBoxItem');
  goog.require('goog.ui.Component');
  goog.require('goog.ui.ControlRenderer');
  goog.require('goog.ui.LabelInput');
  goog.require('goog.ui.Menu');
  goog.require('goog.ui.MenuItem');
  
  var comboBox;
  var input;
  
  function setUp() {
    goog.dom.getElement('combo').innerHTML = '';
  
    comboBox = new goog.ui.ComboBox();
    comboBox.setDefaultText('Select a color...');
    comboBox.addItem(new goog.ui.ComboBoxItem('Red'));
    comboBox.addItem(new goog.ui.ComboBoxItem('Maroon'));
    comboBox.addItem(new goog.ui.ComboBoxItem('Gre<en'));
    comboBox.addItem(new goog.ui.ComboBoxItem('Blue'));
    comboBox.addItem(new goog.ui.ComboBoxItem('Royal Blue'));
    comboBox.addItem(new goog.ui.ComboBoxItem('Yellow'));
    comboBox.addItem(new goog.ui.ComboBoxItem('Magenta'));
    comboBox.addItem(new goog.ui.ComboBoxItem('Mouve'));
    comboBox.addItem(new goog.ui.ComboBoxItem('Grey'));
    comboBox.render(goog.dom.getElement('combo'));
  
    input = comboBox.getInputElement();
  }
  
  function tearDown() {
    comboBox.dispose();
  }
  
  function testInputElementAttributes() {
    var comboBox = new goog.ui.ComboBox();
    comboBox.setFieldName('a_form_field');
    comboBox.createDom();
    var inputElement = comboBox.getInputElement();
    assertEquals('text', inputElement.type);
    assertEquals('a_form_field', inputElement.name);
    assertEquals('off', inputElement.autocomplete);
    comboBox.dispose();
  }
  
  function testSetDefaultText() {
    assertEquals('Select a color...', comboBox.getDefaultText());
    comboBox.setDefaultText('new default text...');
    assertEquals('new default text...', comboBox.getDefaultText());
    assertEquals('new default text...', comboBox.labelInput_.getLabel());
  }
  
  function testGetMenu() {
    assertTrue('Menu should be instance of goog.ui.Menu',
        comboBox.getMenu() instanceof goog.ui.Menu);
    assertEquals('Menu should have correct number of children',
        9, comboBox.getMenu().getChildCount());
  }
  
  function testMenuBeginsInvisible() {
    assertFalse('Menu should begin invisible', comboBox.getMenu().isVisible());
  }
  
  function testClickCausesPopup() {
    goog.testing.events.fireClickSequence(input);
    assertTrue('Menu becomes visible after click',
        comboBox.getMenu().isVisible());
  }
  
  function testUpKeyCausesPopup() {
    goog.testing.events.fireKeySequence(input, goog.events.KeyCodes.UP);
    assertTrue('Menu becomes visible after UP key',
        comboBox.getMenu().isVisible());
  }
  
  function testActionSelectsItem() {
    comboBox.getMenu().getItemAt(2).dispatchEvent(
        goog.ui.Component.EventType.ACTION);
    assertEquals('Gre<en', input.value);
  }
  
  function testActionSelectsItemWithModel() {
    var itemWithModel = new goog.ui.MenuItem('one', 1);
    comboBox.addItem(itemWithModel);
    itemWithModel.dispatchEvent(goog.ui.Component.EventType.ACTION);
    assertEquals('one', comboBox.getValue());
  }
  
  function testRedisplayMenuAfterBackspace() {
    input.value = 'mx';
    comboBox.onInputEvent_();
    input.value = 'm';
    comboBox.onInputEvent_();
    assertEquals('Three items should be displayed',
        3, comboBox.getNumberOfVisibleItems_());
  }
  
  function testExternallyCreatedMenu() {
    var menu = new goog.ui.Menu();
    menu.decorate(goog.dom.getElement('menu'));
    assertTrue('Menu items should be instances of goog.ui.ComboBoxItem',
        menu.getChildAt(0) instanceof goog.ui.ComboBoxItem);
  
    comboBox = new goog.ui.ComboBox(null, menu);
    comboBox.render(goog.dom.getElement('combo'));
  
    input = comboBox.getElement().getElementsByTagName(
        goog.dom.TagName.INPUT)[0];
    menu.getItemAt(2).dispatchEvent(
        goog.ui.Component.EventType.ACTION);
    assertEquals('Blue', input.value);
  }
  
  function testRecomputeVisibleCountAfterChangingItems() {
    input.value = 'Black';
    comboBox.onInputEvent_();
    assertEquals('No items should be displayed',
        0, comboBox.getNumberOfVisibleItems_());
    comboBox.addItem(new goog.ui.ComboBoxItem('Black'));
    assertEquals('One item should be displayed',
        1, comboBox.getNumberOfVisibleItems_());
  
    input.value = 'Red';
    comboBox.onInputEvent_();
    assertEquals('One item should be displayed',
        1, comboBox.getNumberOfVisibleItems_());
    comboBox.removeItemAt(0);  // Red
    assertEquals('No items should be displayed',
        0, comboBox.getNumberOfVisibleItems_());
  }
  
  function testSetEnabled() {
    // By default, everything should be enabled.
    assertFalse('Text input should initially not be disabled', input.disabled);
    assertFalse('Text input should initially not look disabled',
        goog.dom.classlist.contains(input,
        goog.getCssName(goog.ui.LabelInput.prototype.labelCssClassName,
            'disabled')));
    assertFalse('Combo box should initially not look disabled',
        goog.dom.classlist.contains(comboBox.getElement(),
        goog.getCssName('goog-combobox-disabled')));
    goog.testing.events.fireClickSequence(comboBox.getElement());
    assertTrue('Menu initially becomes visible after click',
        comboBox.getMenu().isVisible());
    goog.testing.events.fireClickSequence(document);
    assertFalse('Menu initially becomes invisible after document click',
        comboBox.getMenu().isVisible());
  
    assertTrue(comboBox.isEnabled());
    comboBox.setEnabled(false);
    assertFalse(comboBox.isEnabled());
    assertTrue('Text input should be disabled after being disabled',
        input.disabled);
    assertTrue('Text input should appear disabled after being disabled',
        goog.dom.classlist.contains(input,
        goog.getCssName(goog.ui.LabelInput.prototype.labelCssClassName,
            'disabled')));
    assertTrue('Combo box should appear disabled after being disabled',
        goog.dom.classlist.contains(comboBox.getElement(),
        goog.getCssName('goog-combobox-disabled')));
    goog.testing.events.fireClickSequence(comboBox.getElement());
    assertFalse('Menu should not become visible after click if disabled',
        comboBox.getMenu().isVisible());
  
    comboBox.setEnabled(true);
    assertTrue(comboBox.isEnabled());
    assertFalse('Text input should not be disabled after being re-enabled',
        input.disabled);
    assertFalse('Text input should not appear disabled after being re-enabled',
        goog.dom.classlist.contains(input,
        goog.getCssName(goog.ui.LabelInput.prototype.labelCssClassName,
            'disabled')));
    assertFalse('Combo box should not appear disabled after being re-enabled',
        goog.dom.classlist.contains(comboBox.getElement(),
        goog.getCssName('goog-combobox-disabled')));
    goog.testing.events.fireClickSequence(comboBox.getElement());
    assertTrue('Menu becomes visible after click when re-enabled',
        comboBox.getMenu().isVisible());
    goog.testing.events.fireClickSequence(document);
    assertFalse('Menu becomes invisible after document click when re-enabled',
        comboBox.getMenu().isVisible());
  }
  
  function testSetFormatFromToken() {
    var item = new goog.ui.ComboBoxItem('ABc');
    item.setFormatFromToken('b');
    var div = goog.dom.createDom('div');
    new goog.ui.ControlRenderer().setContent(div, item.getContent());
    assertTrue(div.innerHTML == 'A<b>B</b>c' || div.innerHTML == 'A<B>B</B>c');
  }
  
  function testSetValue() {
    var clock = new goog.testing.MockClock(/* autoInstall */ true);
  
    // Get the input focus. Note that both calls are needed to correctly
    // simulate the focus (and setting document.activeElement) across all
    // browsers.
    input.focus();
    goog.testing.events.fireClickSequence(input);
  
    // Simulate text input.
    input.value = 'Black';
    comboBox.onInputEvent_();
    clock.tick();
    assertEquals('No items should be displayed',
        0, comboBox.getNumberOfVisibleItems_());
    assertFalse('Menu should be invisible', comboBox.getMenu().isVisible());
  
    // Programmatic change with the input focus causes the menu visibility to
    // change if needed.
    comboBox.setValue('Blue');
    clock.tick();
    assertTrue('Menu should be visible1', comboBox.getMenu().isVisible());
    assertEquals('One item should be displayed',
        1, comboBox.getNumberOfVisibleItems_());
  
    // Simulate user input to ensure all the items are invisible again, then
    // blur away.
    input.value = 'Black';
    comboBox.onInputEvent_();
    clock.tick();
    input.blur();
    document.body.focus();
    clock.tick(goog.ui.ComboBox.BLUR_DISMISS_TIMER_MS);
    assertEquals('No items should be displayed',
        0, comboBox.getNumberOfVisibleItems_());
    assertFalse('Menu should be invisible', comboBox.getMenu().isVisible());
  
    // Programmatic change without the input focus does not pop up the menu,
    // but still updates the list of visible items within it.
    comboBox.setValue('Blue');
    clock.tick();
    assertFalse('Menu should be invisible', comboBox.getMenu().isVisible());
    assertEquals('Menu should contain one item',
        1, comboBox.getNumberOfVisibleItems_());
  
    // Click on the combobox. The entire menu becomes visible, the last item
    // (programmatically) set is highlighted.
    goog.testing.events.fireClickSequence(comboBox.getElement());
    assertTrue('Menu should be visible2', comboBox.getMenu().isVisible());
    assertEquals('All items should be displayed',
        comboBox.getMenu().getItemCount(), comboBox.getNumberOfVisibleItems_());
    assertEquals('The last item set should be highlighted',
        /* Blue= */ 3, comboBox.getMenu().getHighlightedIndex());
  
    clock.uninstall();
  }
  