1 /*
   2  * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javafx.scene.control;
  27 
  28 import com.sun.javafx.scene.control.infrastructure.KeyModifier;
  29 import com.sun.javafx.scene.control.infrastructure.MouseEventFirer;
  30 import com.sun.javafx.scene.traversal.Direction;
  31 import com.sun.javafx.tk.Toolkit;
  32 import javafx.css.PseudoClass;
  33 
  34 import com.sun.javafx.scene.control.infrastructure.KeyEventFirer;
  35 import com.sun.javafx.scene.control.infrastructure.StageLoader;
  36 import com.sun.javafx.scene.control.skin.ComboBoxListViewSkin;
  37 import com.sun.javafx.scene.control.skin.ListViewSkin;
  38 import com.sun.javafx.scene.control.skin.VirtualFlow;
  39 
  40 import static com.sun.javafx.scene.control.infrastructure.ControlTestUtils.assertStyleClassContains;
  41 import static org.junit.Assert.*;
  42 import static org.junit.Assert.assertEquals;
  43 
  44 import java.util.*;
  45 
  46 import javafx.beans.property.ObjectProperty;
  47 import javafx.beans.property.SimpleObjectProperty;
  48 import javafx.beans.property.SimpleStringProperty;
  49 import javafx.beans.property.StringProperty;
  50 import javafx.beans.value.ChangeListener;
  51 import javafx.beans.value.ObservableValue;
  52 import javafx.collections.FXCollections;
  53 import javafx.collections.ObservableList;
  54 import javafx.event.ActionEvent;
  55 import javafx.event.Event;
  56 import javafx.event.EventHandler;
  57 import javafx.scene.Group;
  58 import javafx.scene.Node;
  59 import javafx.scene.Scene;
  60 import javafx.scene.input.KeyCode;
  61 import javafx.scene.layout.StackPane;
  62 import javafx.scene.layout.VBox;
  63 import javafx.scene.paint.Color;
  64 import javafx.scene.shape.Circle;
  65 import javafx.stage.Stage;
  66 import javafx.util.Callback;
  67 import javafx.util.StringConverter;
  68 
  69 import org.junit.Before;
  70 import org.junit.Ignore;
  71 import org.junit.Test;
  72 
  73 public class ComboBoxTest {
  74     private ComboBox<String> comboBox;
  75     private SingleSelectionModel<String> sm;
  76     
  77     /*********************************************************************
  78      *                                                                   *
  79      * Utility methods                                                   *
  80      *                                                                   *
  81      ********************************************************************/    
  82     
  83     public ListView getListView() {
  84         return ((ComboBoxListViewSkin)comboBox.getSkin()).getListView();
  85     }
  86     
  87     public Node getDisplayNode() {
  88         return ((ComboBoxListViewSkin)comboBox.getSkin()).getDisplayNode();
  89     }
  90     
  91     
  92     
  93     /*********************************************************************
  94      *                                                                   *
  95      * Setup                                                             *
  96      *                                                                   *
  97      ********************************************************************/      
  98     
  99     @Before public void setup() {
 100         comboBox = new ComboBox<String>();
 101         comboBox.setSkin(new ComboBoxListViewSkin<>(comboBox));
 102         sm = comboBox.getSelectionModel();
 103     }
 104     
 105     
 106     
 107     /*********************************************************************
 108      *                                                                   *
 109      * Tests for the constructors                                        *
 110      *                                                                   *
 111      ********************************************************************/
 112     
 113     @Test public void noArgConstructorSetsTheStyleClass() {
 114         assertStyleClassContains(comboBox, "combo-box");
 115     }
 116     
 117     @Test public void noArgConstructorSetsNonNullSelectionModel() {
 118         assertNotNull(sm);
 119     }
 120     
 121     @Test public void noArgConstructorSetsNonNullItems() {
 122         assertNotNull(comboBox.getItems());
 123     }
 124     
 125     @Test public void noArgConstructor_selectedItemIsNull() {
 126         assertNull(sm.getSelectedItem());
 127     }
 128     
 129     @Test public void noArgConstructor_selectedIndexIsNegativeOne() {
 130         assertEquals(-1, sm.getSelectedIndex());
 131     }
 132     
 133     @Test public void noArgConstructor_valueIsNull() {
 134         assertNull(comboBox.getValue());
 135     }
 136     
 137     @Test public void noArgConstructor_editableIsFalse() {
 138         assertFalse(comboBox.isEditable());
 139     }
 140     
 141     @Test public void noArgConstructor_showingIsFalse() {
 142         assertFalse(comboBox.isShowing());
 143     }
 144     
 145     @Test public void noArgConstructor_promptTextIsEmptyString() {
 146         assertEquals("", comboBox.getPromptText());
 147     }
 148     
 149     @Test public void noArgConstructor_placeholderIsNull() {
 150         assertNull(comboBox.getPlaceholder());
 151     }
 152     
 153     @Test public void noArgConstructor_armedIsFalse() {
 154         assertFalse(comboBox.isArmed());
 155     }
 156     
 157     @Test public void noArgConstructor_converterIsNotNull() {
 158         assertNotNull(comboBox.getConverter());
 159     }
 160     
 161     @Test public void noArgConstructor_cellFactoryIsNull() {
 162         assertNull(comboBox.getCellFactory());
 163     }
 164     
 165     @Test public void noArgConstructor_visibleRowFactoryIs10() {
 166         assertEquals(10, comboBox.getVisibleRowCount());
 167     }
 168     
 169     @Test public void singleArgConstructorSetsTheStyleClass() {
 170         final ComboBox<String> b2 = new ComboBox<String>(FXCollections.observableArrayList("Hi"));
 171         assertStyleClassContains(b2, "combo-box");
 172     }
 173     
 174     @Test public void singleArgConstructorSetsNonNullSelectionModel() {
 175         final ComboBox<String> b2 = new ComboBox<String>(FXCollections.observableArrayList("Hi"));
 176         assertNotNull(b2.getSelectionModel());
 177     }
 178 
 179     @Test public void singleArgConstructorAllowsNullItems() {
 180         final ComboBox<String> b2 = new ComboBox<String>(null);
 181         assertNull(b2.getItems());
 182     }
 183     
 184     @Test public void singleArgConstructorTakesItems() {
 185         ObservableList<String> items = FXCollections.observableArrayList("Hi");
 186         final ComboBox<String> b2 = new ComboBox<String>(items);
 187         assertSame(items, b2.getItems());
 188     }
 189     
 190     @Test public void singleArgConstructor_selectedItemIsNull() {
 191         final ComboBox<String> b2 = new ComboBox<String>(FXCollections.observableArrayList("Hi"));
 192         assertNull(b2.getSelectionModel().getSelectedItem());
 193     }
 194     
 195     @Test public void singleArgConstructor_selectedIndexIsNegativeOne() {
 196         final ComboBox<String> b2 = new ComboBox<String>(FXCollections.observableArrayList("Hi"));
 197         assertEquals(-1, b2.getSelectionModel().getSelectedIndex());
 198     }
 199     
 200     @Test public void singleArgConstructor_valueIsNull() {
 201         final ComboBox<String> b2 = new ComboBox<String>(FXCollections.observableArrayList("Hi"));
 202         assertNull(b2.getValue());
 203     }
 204     
 205     @Test public void singleArgConstructor_editableIsFalse() {
 206         final ComboBox<String> b2 = new ComboBox<String>(FXCollections.observableArrayList("Hi"));
 207         assertFalse(b2.isEditable());
 208     }
 209     
 210     @Test public void singleArgConstructor_showingIsFalse() {
 211         final ComboBox<String> b2 = new ComboBox<String>(FXCollections.observableArrayList("Hi"));
 212         assertFalse(b2.isShowing());
 213     }
 214     
 215     @Test public void singleArgConstructor_promptTextIsEmptyString() {
 216         final ComboBox<String> b2 = new ComboBox<String>(FXCollections.observableArrayList("Hi"));
 217         assertEquals("", b2.getPromptText());
 218     }
 219     
 220     @Test public void singleArgConstructor_placeholderIsNull() {
 221         final ComboBox<String> b2 = new ComboBox<String>(FXCollections.observableArrayList("Hi"));
 222         assertNull(b2.getPlaceholder());
 223     }
 224     
 225     @Test public void singleArgConstructor_armedIsFalse() {
 226         final ComboBox<String> b2 = new ComboBox<String>(FXCollections.observableArrayList("Hi"));
 227         assertEquals(false, b2.isArmed());
 228     }
 229     
 230     @Test public void singleArgConstructor_converterIsNotNull() {
 231         final ComboBox<String> b2 = new ComboBox<String>(FXCollections.observableArrayList("Hi"));
 232         assertNotNull(b2.getConverter());
 233     }
 234     
 235     @Test public void singleArgConstructor_cellFactoryIsNull() {
 236         final ComboBox<String> b2 = new ComboBox<String>(FXCollections.observableArrayList("Hi"));
 237         assertNull(b2.getCellFactory());
 238     }
 239     
 240     @Test public void singleArgConstructor_visibleRowFactoryIs10() {
 241         final ComboBox<String> b2 = new ComboBox<String>(FXCollections.observableArrayList("Hi"));
 242         assertEquals(10, b2.getVisibleRowCount());
 243     }
 244     
 245     /*********************************************************************
 246      * Tests for selection model                                         *
 247      ********************************************************************/
 248     
 249     @Test public void selectionModelCanBeNull() {
 250         comboBox.setSelectionModel(null);
 251         assertNull(comboBox.getSelectionModel());
 252     }
 253 
 254     @Test public void selectionModelCanBeBound() {
 255         SingleSelectionModel<String> sm = new ComboBox.ComboBoxSelectionModel<String>(comboBox);
 256         ObjectProperty<SingleSelectionModel<String>> other = new SimpleObjectProperty<SingleSelectionModel<String>>(sm);
 257         comboBox.selectionModelProperty().bind(other);
 258         assertSame(sm, sm);
 259     }
 260 
 261     @Test public void selectionModelCanBeChanged() {
 262         SingleSelectionModel<String> sm = new ComboBox.ComboBoxSelectionModel<String>(comboBox);
 263         comboBox.setSelectionModel(sm);
 264         assertSame(sm, sm);
 265     }
 266     
 267     @Test public void canSetSelectedItemToAnItemEvenWhenThereAreNoItems() {
 268         final String randomString = new String("I AM A CRAZY RANDOM STRING");
 269         sm.select(randomString);
 270         assertEquals(-1, sm.getSelectedIndex());
 271         assertSame(randomString, sm.getSelectedItem());
 272     }
 273         
 274     @Test public void canSetSelectedItemToAnItemNotInTheDataModel() {
 275         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 276         final String randomString = new String("I AM A CRAZY RANDOM STRING");
 277         sm.select(randomString);
 278         assertEquals(-1, sm.getSelectedIndex());
 279         assertSame(randomString, sm.getSelectedItem());
 280     }
 281         
 282     @Test public void settingTheSelectedItemToAnItemInItemsResultsInTheCorrectSelectedIndex() {
 283         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 284         sm.select("Orange");
 285         assertEquals(1, sm.getSelectedIndex());
 286         assertSame("Orange", sm.getSelectedItem());
 287     }
 288     
 289     @Test public void settingTheSelectedItemToANonexistantItemAndThenSettingItemsWhichContainsItResultsInCorrectSelectedIndex() {
 290         sm.select("Orange");
 291         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 292         assertEquals(1, sm.getSelectedIndex());
 293         assertSame("Orange", sm.getSelectedItem());
 294     }
 295     
 296     @Test public void ensureSelectionClearsWhenAllItemsAreRemoved_selectIndex0() {
 297         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 298         sm.select(0);
 299         comboBox.getItems().clear();
 300         assertEquals(-1, sm.getSelectedIndex());
 301         assertEquals(null, sm.getSelectedItem());
 302     }
 303     
 304     @Test public void ensureSelectionClearsWhenAllItemsAreRemoved_selectIndex2() {
 305         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 306         sm.select(2);
 307         comboBox.getItems().clear();
 308         assertEquals(-1, sm.getSelectedIndex());
 309         assertEquals(null, sm.getSelectedItem());
 310     }
 311     
 312     @Test public void ensureSelectedItemRemainsAccurateWhenItemsAreCleared() {
 313         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 314         sm.select(2);
 315         comboBox.getItems().clear();
 316         assertNull(sm.getSelectedItem());
 317         assertEquals(-1, sm.getSelectedIndex());
 318         
 319         comboBox.getItems().addAll("Kiwifruit", "Mandarin", "Pineapple");
 320         sm.select(2);
 321         assertEquals("Pineapple", sm.getSelectedItem());
 322     }
 323     
 324     @Test public void ensureSelectionShiftsDownWhenOneNewItemIsAdded() {
 325         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 326         sm.select(1);
 327         assertEquals(1, sm.getSelectedIndex());
 328         assertEquals("Orange", sm.getSelectedItem());
 329         
 330         comboBox.getItems().add(0, "Kiwifruit");
 331         assertEquals(2, sm.getSelectedIndex());
 332         assertEquals("Orange", sm.getSelectedItem());
 333     }
 334     
 335     @Test public void ensureSelectionShiftsDownWhenMultipleNewItemAreAdded() {
 336         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 337         sm.select(1);
 338         assertEquals(1, sm.getSelectedIndex());
 339         assertEquals("Orange", sm.getSelectedItem());
 340         
 341         comboBox.getItems().addAll(0, Arrays.asList("Kiwifruit", "Pineapple", "Mandarin"));
 342         assertEquals("Orange", sm.getSelectedItem());
 343         assertEquals(4, sm.getSelectedIndex());
 344     }
 345     
 346     @Test public void ensureSelectionShiftsUpWhenOneItemIsRemoved() {
 347         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 348         sm.select(1);
 349         assertEquals(1, sm.getSelectedIndex());
 350         assertEquals("Orange", sm.getSelectedItem());
 351         
 352         comboBox.getItems().remove("Apple");
 353         assertEquals(0, sm.getSelectedIndex());
 354         assertEquals("Orange", sm.getSelectedItem());
 355     }
 356     
 357     @Test public void ensureSelectionShiftsUpWheMultipleItemsAreRemoved() {
 358         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 359         sm.select(2);
 360         assertEquals(2, sm.getSelectedIndex());
 361         assertEquals("Banana", sm.getSelectedItem());
 362         
 363         comboBox.getItems().removeAll(Arrays.asList("Apple", "Orange"));
 364         assertEquals(0, sm.getSelectedIndex());
 365         assertEquals("Banana", sm.getSelectedItem());
 366     }
 367     
 368     @Test public void ensureSelectionIsCorrectWhenItemsChange() {
 369         comboBox.setItems(FXCollections.observableArrayList("Item 1"));
 370         sm.select(0);
 371         assertEquals("Item 1", sm.getSelectedItem());
 372         
 373         comboBox.setItems(FXCollections.observableArrayList("Item 2"));
 374         assertEquals(-1, sm.getSelectedIndex());
 375         assertEquals(null, sm.getSelectedItem());
 376     }
 377     
 378     @Test(expected=NullPointerException.class) 
 379     public void selectionModelComboBoxReferenceCanNotBeNull() {
 380         new ComboBox.ComboBoxSelectionModel<String>(null);
 381     }
 382     
 383     @Test public void ensureGetModelItemOutOfBoundsWorks_1() {
 384         ComboBox cb = new ComboBox(null);
 385         cb.getSelectionModel().select(-1);
 386         assertEquals(-1, cb.getSelectionModel().getSelectedIndex());
 387     }
 388     
 389     @Test public void ensureGetModelItemOutOfBoundsWorks_2() {
 390         ComboBox cb = new ComboBox(null);
 391         cb.getSelectionModel().select(0);
 392         assertEquals(-1, cb.getSelectionModel().getSelectedIndex());
 393     }
 394     
 395     @Test public void test_rt15793() {
 396         // ComboBox selectedIndex is 0 although the items list is empty
 397         final ComboBox lv = new ComboBox();
 398         final ObservableList list = FXCollections.observableArrayList();
 399         lv.setItems(list);
 400         list.add("toto");
 401         lv.getSelectionModel().select(0);
 402         assertEquals(0, lv.getSelectionModel().getSelectedIndex());
 403         list.remove(0);
 404         assertEquals(-1, lv.getSelectionModel().getSelectedIndex());
 405     }
 406     
 407     @Test public void ensureSelectionModelUpdatesValueProperty_withSelectIndex() {
 408         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 409         assertNull(comboBox.getValue());
 410         sm.select(0);
 411         assertEquals("Apple", comboBox.getValue());
 412     }
 413     
 414     @Test public void ensureSelectionModelUpdatesValueProperty_withSelectItem() {
 415         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 416         assertNull(comboBox.getValue());
 417         sm.select("Apple");
 418         assertEquals("Apple", comboBox.getValue());
 419     }
 420     
 421     @Test public void ensureSelectionModelUpdatesValueProperty_withSelectPrevious() {
 422         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 423         assertNull(comboBox.getValue());
 424         sm.select(2);
 425         sm.selectPrevious();
 426         assertEquals("Orange", comboBox.getValue());
 427     }
 428     
 429     @Test public void ensureSelectionModelUpdatesValueProperty_withSelectNext() {
 430         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 431         assertNull(comboBox.getValue());
 432         sm.select("Apple");
 433         sm.selectNext();
 434         assertEquals("Orange", comboBox.getValue());
 435     }
 436     
 437     @Test public void ensureSelectionModelUpdatesValueProperty_withSelectFirst() {
 438         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 439         assertNull(comboBox.getValue());
 440         sm.selectFirst();
 441         assertEquals("Apple", comboBox.getValue());
 442     }
 443     
 444     @Test public void ensureSelectionModelUpdatesValueProperty_withSelectLast() {
 445         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 446         assertNull(comboBox.getValue());
 447         sm.selectLast();
 448         assertEquals("Banana", comboBox.getValue());
 449     }
 450     
 451     @Test public void ensureSelectionModelClearsValueProperty() {
 452         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 453         assertNull(comboBox.getValue());
 454         sm.select(0);
 455         assertEquals("Apple", comboBox.getValue());
 456         
 457         sm.clearSelection();
 458         assertNull(comboBox.getValue());
 459     }
 460     
 461     @Test public void ensureSelectionModelClearsValuePropertyWhenNegativeOneSelected() {
 462         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 463         assertNull(comboBox.getValue());
 464         sm.select(0);
 465         assertEquals("Apple", comboBox.getValue());
 466         
 467         sm.select(-1);
 468         assertNull("Expected null, actual value: " + comboBox.getValue(), comboBox.getValue());
 469     }
 470     
 471     @Test public void ensureValueIsCorrectWhenItemsIsAddedToWithExistingSelection() {
 472         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 473         sm.select(1);
 474         
 475         comboBox.getItems().add(0, "Kiwifruit");
 476         
 477         assertEquals(2, sm.getSelectedIndex());
 478         assertEquals("Orange", sm.getSelectedItem());
 479         assertEquals("Orange", comboBox.getValue());
 480     }
 481     
 482     @Test public void ensureValueIsCorrectWhenItemsAreRemovedWithExistingSelection() {
 483         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 484         sm.select(1);
 485         
 486         comboBox.getItems().remove("Apple");
 487         
 488         assertEquals(0, sm.getSelectedIndex());
 489         assertEquals("Orange", sm.getSelectedItem());
 490         assertEquals("Orange", comboBox.getValue());
 491     }
 492     
 493     @Test public void ensureValueIsUpdatedByCorrectSelectionModelWhenSelectionModelIsChanged() {
 494         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 495         SingleSelectionModel sm1 = sm;
 496         sm1.select(1);
 497         assertEquals("Orange", comboBox.getValue());
 498         
 499         SingleSelectionModel sm2 = new ComboBox.ComboBoxSelectionModel(comboBox);
 500         comboBox.setSelectionModel(sm2);
 501         
 502         sm1.select(2);  // value should not change as we are using old SM
 503         assertEquals("Orange", comboBox.getValue());
 504         
 505         sm2.select(0);  // value should change, as we are using new SM
 506         assertEquals("Apple", comboBox.getValue());
 507     }
 508     
 509     @Test public void ensureValueDoesNotChangeWhenBoundAndNoExceptions() {
 510         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 511         
 512         StringProperty sp = new SimpleStringProperty("empty");
 513         comboBox.valueProperty().bind(sp);
 514         
 515         sm.select(1);
 516         assertEquals("empty", comboBox.getValue());
 517     }
 518     
 519     @Test public void ensureSelectionModelUpdatesWhenValueChanges() {
 520         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 521         assertNull(sm.getSelectedItem());
 522         comboBox.setValue("Orange");
 523         assertEquals("Orange", sm.getSelectedItem());
 524     }
 525     
 526     @Test public void ensureSelectionModelUpdatesWhenValueChangesToNull() {
 527         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 528         comboBox.setValue("Kiwifruit");
 529         assertEquals("Kiwifruit", sm.getSelectedItem());
 530         assertEquals("Kiwifruit", comboBox.getValue());
 531         comboBox.setValue(null);
 532         assertEquals(null, sm.getSelectedItem());
 533         assertEquals(-1, sm.getSelectedIndex());
 534         assertEquals(null, comboBox.getValue());
 535     }
 536     
 537     @Test public void ensureValueEqualsSelectedItemWhenNotInItemsList() {
 538         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 539         sm.setSelectedItem("pineapple");
 540         assertEquals("pineapple", sm.getSelectedItem());
 541         assertEquals("pineapple", comboBox.getValue());
 542     }
 543     
 544     /*********************************************************************
 545      * Tests for default values                                         *
 546      ********************************************************************/
 547     
 548     @Test public void checkPromptTextPropertyName() {
 549         assertTrue(comboBox.promptTextProperty().getName().equals("promptText"));
 550     }
 551     
 552     @Test public void checkPlaceholderPropertyName() {
 553         assertTrue(comboBox.placeholderProperty().getName().equals("placeholder"));
 554     }
 555     
 556     @Test public void checkValuePropertyName() {
 557         assertTrue(comboBox.valueProperty().getName().equals("value"));
 558     }
 559     
 560     @Test public void checkItemsPropertyName() {
 561         assertTrue(comboBox.itemsProperty().getName().equals("items"));
 562     }
 563     
 564     @Test public void checkConverterPropertyName() {
 565         assertTrue(comboBox.converterProperty().getName().equals("converter"));
 566     }
 567     
 568     @Test public void checkSelectionModelPropertyName() {
 569         assertTrue(comboBox.selectionModelProperty().getName().equals("selectionModel"));
 570     }
 571     
 572     @Test public void checkVisibleRowCountPropertyName() {
 573         assertTrue(comboBox.visibleRowCountProperty().getName().equals("visibleRowCount"));
 574     }
 575     
 576     @Test public void checkOnActionPropertyName() {
 577         assertTrue(comboBox.onActionProperty().getName().equals("onAction"));
 578     }
 579     
 580     @Test public void checkArmedPropertyName() {
 581         assertTrue(comboBox.armedProperty().getName().equals("armed"));
 582     }
 583     
 584     @Test public void checkShowingPropertyName() {
 585         assertTrue(comboBox.showingProperty().getName().equals("showing"));
 586     }
 587     
 588     @Test public void checkEditablePropertyName() {
 589         assertTrue(comboBox.editableProperty().getName().equals("editable"));
 590     }
 591     
 592     @Test public void checkCellFactoryPropertyName() {
 593         assertTrue(comboBox.cellFactoryProperty().getName().equals("cellFactory"));
 594     }
 595     
 596     @Test public void defaultActionHandlerIsNotDefined() {
 597         assertNull(comboBox.getOnAction());
 598     }
 599     
 600     @Test public void defaultConverterCanHandleStringValues() {
 601         StringConverter<String> sc = comboBox.getConverter();
 602         assertEquals("input", sc.fromString("input"));
 603         assertEquals("input", sc.toString("input"));
 604     }
 605     
 606     @Test public void defaultConverterCanHandleIncorrectType_1() {
 607         ComboBox cb = new ComboBox();
 608         StringConverter sc = cb.getConverter();
 609         assertEquals("42", sc.toString(new Integer(42)));
 610     }
 611     
 612     @Test(expected=ClassCastException.class)
 613     public void defaultConverterCanHandleIncorrectType_2() {
 614         ComboBox<Integer> cb = new ComboBox<Integer>();
 615         StringConverter<Integer> sc = cb.getConverter();
 616         Integer value = sc.fromString("42");
 617     }
 618     
 619     @Test public void defaultConverterCanHandleNullValues() {
 620         StringConverter<String> sc = comboBox.getConverter();
 621         assertEquals(null, sc.fromString(null));
 622         assertEquals(null, sc.toString(null));
 623     }
 624     
 625     @Test public void ensureImpl_getPseudoClassStateReturnsValidValue() {
 626         Set<PseudoClass> pseudoClassStates = comboBox.getPseudoClassStates();
 627         assertFalse(comboBox.isEditable());
 628         assertTrue(pseudoClassStates.size() >= 0);
 629 
 630         comboBox.setEditable(true);
 631         pseudoClassStates = comboBox.getPseudoClassStates();
 632         assertTrue(pseudoClassStates.contains(PseudoClass.getPseudoClass("editable")));
 633 
 634         comboBox.setEditable(false);
 635         pseudoClassStates = comboBox.getPseudoClassStates();
 636         assertTrue(pseudoClassStates.contains(PseudoClass.getPseudoClass("editable")) == false);
 637 
 638         comboBox.show();
 639         pseudoClassStates = comboBox.getPseudoClassStates();
 640         assertTrue(pseudoClassStates.contains(PseudoClass.getPseudoClass("showing")));
 641 
 642         comboBox.hide();
 643         pseudoClassStates = comboBox.getPseudoClassStates();
 644         assertTrue(pseudoClassStates.contains(PseudoClass.getPseudoClass("showing")) == false);
 645 
 646         comboBox.arm();
 647         pseudoClassStates = comboBox.getPseudoClassStates();
 648         assertTrue(pseudoClassStates.contains(PseudoClass.getPseudoClass("armed")));
 649         
 650     }
 651     
 652     /*********************************************************************
 653      * Tests for properties                                              *
 654      ********************************************************************/
 655     
 656     @Test public void ensureAllowsNullConverter() {
 657         comboBox.setConverter(null);
 658         assertNull(comboBox.getConverter());
 659     }
 660     
 661     @Test public void ensureCanSetNonNullCellFactory() {
 662         Callback<ListView<String>, ListCell<String>> cf = p -> null;
 663         comboBox.setCellFactory(cf);
 664         assertEquals(cf, comboBox.getCellFactory());
 665     }
 666     
 667     @Test public void ensureEditorIsNonNullWhenComboBoxIsNotEditable() {
 668         assertNotNull(comboBox.getEditor());
 669     }
 670     
 671     @Test public void ensureEditorIsNonNullWhenComboBoxIsEditable() {
 672         comboBox.setEditable(true);
 673         assertNotNull(comboBox.getEditor());
 674     }
 675     
 676     @Test public void ensureEditorDoesNotChangeWhenEditableToggles() {
 677         comboBox.setEditable(true);
 678         assertNotNull(comboBox.getEditor());
 679         comboBox.setEditable(false);
 680         assertNotNull(comboBox.getEditor());
 681         comboBox.setEditable(true);
 682         assertNotNull(comboBox.getEditor());
 683     }
 684     
 685     @Test public void ensureCanSetValueToNonNullStringAndBackAgain() {
 686         comboBox.setValue("Test 123");
 687         assertEquals("Test 123", comboBox.getValue());
 688         comboBox.setValue(null);
 689         assertNull(comboBox.getValue());
 690     }
 691     
 692     @Test public void ensureCanToggleEditable() {
 693         comboBox.setEditable(true);
 694         assertTrue(comboBox.isEditable());
 695         comboBox.setEditable(false);
 696         assertFalse(comboBox.isEditable());
 697     }
 698     
 699     @Test public void ensureCanToggleShowing() {
 700         comboBox.show();
 701         assertTrue(comboBox.isShowing());
 702         comboBox.hide();
 703         assertFalse(comboBox.isShowing());
 704     }
 705     
 706     @Test public void ensureCanNotToggleShowingWhenDisabled() {
 707         comboBox.setDisable(true);
 708         comboBox.show();
 709         assertFalse(comboBox.isShowing());
 710         comboBox.setDisable(false);
 711         comboBox.show();
 712         assertTrue(comboBox.isShowing());
 713     }
 714     
 715     @Test public void ensureCanSetPromptText() {
 716         comboBox.setPromptText("Test 1 2 3");
 717         assertEquals("Test 1 2 3", comboBox.getPromptText());
 718     }
 719     
 720     @Test public void ensureCanSetPromptTextToNull() {
 721         assertEquals("", comboBox.getPromptText());
 722         comboBox.setPromptText(null);
 723         assertEquals(null, comboBox.getPromptText());
 724     }
 725     
 726     @Test public void ensurePromptTextStripsNewlines() {
 727         comboBox.setPromptText("Test\n1\n2\n3");
 728         assertEquals("Test123", comboBox.getPromptText());
 729     }
 730     
 731     @Test public void ensureCanSetPlaceholder() {
 732         Label label = new javafx.scene.control.Label("Test 1 2 3");
 733         comboBox.setPlaceholder(label);
 734         assertEquals(label, comboBox.getPlaceholder());
 735     }
 736     
 737     @Test public void ensureCanToggleArmed() {
 738         assertFalse(comboBox.isArmed());
 739         comboBox.arm();
 740         assertTrue(comboBox.isArmed());
 741         comboBox.disarm();
 742         assertFalse(comboBox.isArmed());
 743     }
 744     
 745     @Test public void ensureCanSetVisibleRowCount() {
 746         comboBox.setVisibleRowCount(13);
 747         assertEquals(13, comboBox.getVisibleRowCount());
 748     }
 749     
 750     @Test public void ensureCanSetVisibleRowCountToNegativeValues() {
 751         comboBox.setVisibleRowCount(-10);
 752         assertEquals(-10, comboBox.getVisibleRowCount());
 753     }
 754     
 755     @Test public void ensureCanSetOnAction() {
 756         EventHandler<ActionEvent> onAction = t -> { };
 757         comboBox.setOnAction(onAction);
 758         assertEquals(onAction, comboBox.getOnAction());
 759     }
 760     
 761     @Test public void ensureOnActionPropertyReferencesBean() {
 762         assertEquals(comboBox, comboBox.onActionProperty().getBean());
 763     }
 764     
 765     /*********************************************************************
 766      * Tests for property binding                                        *
 767      ********************************************************************/
 768     @Test public void checkPromptTextPropertyBind() {
 769         StringProperty strPr = new SimpleStringProperty("value");
 770         comboBox.promptTextProperty().bind(strPr);
 771         assertTrue("PromptText cannot be bound", comboBox.getPromptText().equals("value"));
 772         strPr.setValue("newvalue");
 773         assertTrue("PromptText cannot be bound", comboBox.getPromptText().equals("newvalue"));
 774     }
 775     
 776     @Test public void checkValuePropertyBind() {
 777         StringProperty strPr = new SimpleStringProperty("value");
 778         comboBox.valueProperty().bind(strPr);
 779         assertTrue("value cannot be bound", comboBox.getValue().equals("value"));
 780         strPr.setValue("newvalue");
 781         assertTrue("value cannot be bound", comboBox.getValue().equals("newvalue"));
 782     }
 783     
 784     
 785     
 786     /*********************************************************************
 787      * Tests for bug reports                                             *
 788      ********************************************************************/    
 789     
 790     @Test public void test_rt18972() {
 791         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 792         sm.select(1);
 793         assertTrue(sm.isSelected(1));
 794         
 795         comboBox.setEditable(true);
 796         comboBox.setValue("New Value");
 797         
 798         // there should be no selection in the selection model, as "New Value" 
 799         // isn't an item in the list, however, it is a totally valid value for
 800         // the value property
 801         assertFalse(sm.isSelected(1));      
 802         assertEquals("New Value", sm.getSelectedItem());
 803         assertEquals("New Value", comboBox.getValue());
 804         
 805         comboBox.setEditable(false);
 806         assertEquals(-1, sm.getSelectedIndex());
 807         assertEquals("New Value", sm.getSelectedItem());
 808         assertEquals("New Value", comboBox.getValue());
 809     }
 810     
 811     @Test public void test_rt18941() {
 812         comboBox.getItems().addAll("Apple", "Orange", "Banana");
 813         comboBox.setValue("Orange");
 814         assertEquals("Orange", comboBox.getValue());
 815         assertEquals("Orange", comboBox.getSelectionModel().getSelectedItem());
 816         assertTrue("Selected Index: " + sm.getSelectedIndex(), sm.isSelected(1));
 817     }
 818     
 819     @Test public void test_rt19227() {
 820         comboBox.getItems().addAll("0","0","0","0","0");
 821         comboBox.getSelectionModel().select(2);
 822         assertEquals("0", comboBox.getValue());
 823         assertEquals("0", comboBox.getSelectionModel().getSelectedItem());
 824         assertTrue(sm.isSelected(2));
 825     }
 826     
 827     @Ignore("Test not working as the heights being returned are not accurate")
 828     @Test public void test_rt20106() {
 829         comboBox.getItems().addAll("0","1","2","3","4","5","6","7","8","9");
 830         
 831         Stage stage = new Stage();
 832         Scene scene = new Scene(comboBox);
 833         stage.setScene(scene);
 834         comboBox.impl_processCSS(true);
 835         comboBox.show();
 836         
 837         comboBox.setVisibleRowCount(5);
 838         double initialHeight = getListView().getHeight();
 839         assertFalse("initialHeight: " + initialHeight, Double.compare(0.0, initialHeight) == 0);
 840         
 841         comboBox.setVisibleRowCount(0);
 842         double smallHeight =    getListView().getHeight();
 843         assertTrue("smallHeight: " + smallHeight + ", initialHeight: " + initialHeight,
 844                 smallHeight != initialHeight && smallHeight < initialHeight);
 845         
 846         comboBox.setVisibleRowCount(7);
 847         double biggerHeight = getListView().getHeight();
 848         assertTrue(biggerHeight != smallHeight && smallHeight < biggerHeight);
 849     } 
 850     
 851     private int count = 0;
 852     @Test public void test_rt20103() {
 853         final TextField tf = new TextField();
 854         
 855         comboBox.setOnAction(t -> {
 856             count++;
 857         });
 858         
 859         assertTrue(count == 0);
 860         
 861         comboBox.valueProperty().bind(tf.textProperty());   // count++ here
 862         assertTrue("count: " + count, count == 1);
 863         
 864         tf.setText("Text1");                                // count++ here
 865         assertTrue("count: " + count, count == 2);
 866         
 867         comboBox.valueProperty().unbind();                  // no count++ here
 868         assertTrue("count: " + count, count == 2);
 869         
 870         comboBox.valueProperty().bindBidirectional(tf.textProperty());  // count++ here
 871         tf.setText("Text2");
 872         assertTrue("count: " + count, count == 3);
 873     } 
 874     
 875     @Ignore("Test not working as the skin is not being properly instantiated")
 876     @Test public void test_rt20100() {
 877         comboBox.getItems().addAll("0","1","2","3","4","5","6","7","8","9");
 878         
 879         Stage stage = new Stage();
 880         Scene scene = new Scene(comboBox);
 881         stage.setScene(scene);
 882         comboBox.impl_processCSS(true);
 883         comboBox.show();
 884         
 885         comboBox.setConverter(new StringConverter() {
 886             int toStringCounter = 0;
 887             int fromStringCounter = 0;
 888 
 889             @Override public String toString(Object t) {
 890                 return "TO_STRING";
 891             }
 892 
 893             @Override public Object fromString(String string) {
 894                 return "FROM_STRING";
 895             }
 896         });
 897         
 898         comboBox.getSelectionModel().select(2);
 899         assertEquals("2", comboBox.getValue());
 900         
 901         ListView listView = getListView();
 902 //        listView.impl_processCSS(true);
 903         
 904         assertEquals("2", listView.getSelectionModel().getSelectedItem());
 905         
 906         System.out.println(listView.getSkin());
 907         
 908         VirtualFlow flow = (VirtualFlow)listView.lookup("#virtual-flow");
 909         assertNotNull(flow);
 910         
 911         IndexedCell cell = flow.getVisibleCell(2);
 912         System.out.println("cell: " + cell);
 913         assertEquals("TO_STRING", cell.getText());
 914     } 
 915     
 916     @Ignore
 917     @Test public void test_rt20189() {
 918         comboBox.getItems().addAll("0","1","2","3","4","5","6","7","8","9");
 919         
 920         Stage stage = new Stage();
 921         Scene scene = new Scene(comboBox);
 922         stage.setScene(scene);
 923         comboBox.impl_processCSS(true);
 924         comboBox.show();
 925         
 926         SelectionModel sm = getListView().getSelectionModel();
 927         
 928         comboBox.getSelectionModel().select(2);
 929         Object item = sm.getSelectedItem();
 930         assertEquals("2", item);
 931         assertEquals(2, sm.getSelectedIndex());
 932         
 933         comboBox.setValue("test");
 934         item = sm.getSelectedItem();
 935         assertEquals("test",item);
 936         assertEquals(-1, sm.getSelectedIndex());
 937         
 938         comboBox.getSelectionModel().select(2);
 939         item = sm.getSelectedItem();
 940         assertEquals("2", item);
 941         assertEquals(2, sm.getSelectedIndex());
 942     }
 943     
 944     @Test public void test_rt27654() {
 945         comboBox.getItems().addAll("0","1","2","3","4","5","6","7","8","9");
 946         
 947         SingleSelectionModel sm = comboBox.getSelectionModel();
 948         
 949         Stage stage = new Stage();
 950         Scene scene = new Scene(comboBox);
 951         stage.setScene(scene);
 952         comboBox.impl_processCSS(true);
 953         comboBox.show();
 954         ListCell<String> buttonCell = (ListCell<String>) getDisplayNode();
 955         
 956         sm.select(2);
 957         assertEquals("2", sm.getSelectedItem());
 958         assertEquals("2", comboBox.getValue());
 959         assertEquals("2", buttonCell.getText());
 960         assertEquals(2, sm.getSelectedIndex());
 961         
 962         sm.clearSelection();
 963         assertNull(sm.getSelectedItem());
 964         assertNull(comboBox.getValue());
 965         assertEquals("", buttonCell.getText());
 966         assertEquals(-1, sm.getSelectedIndex());
 967         
 968         sm.select(2);
 969         assertEquals("2", sm.getSelectedItem());
 970         assertEquals("2", comboBox.getValue());
 971         assertEquals("2", buttonCell.getText());
 972         assertEquals(2, sm.getSelectedIndex());
 973     }
 974     
 975     @Test public void test_rt24412() {
 976         SingleSelectionModel sm = comboBox.getSelectionModel();
 977         
 978         Stage stage = new Stage();
 979         Scene scene = new Scene(comboBox);
 980         stage.setScene(scene);
 981         comboBox.impl_processCSS(true);
 982         comboBox.show();
 983         ListCell<String> buttonCell = (ListCell<String>) getDisplayNode();
 984         
 985         comboBox.getItems().setAll("0","1","2","3","4","5","6","7","8","9");
 986         
 987         sm.select("2");
 988         assertEquals("2", sm.getSelectedItem());
 989         assertEquals("2", comboBox.getValue());
 990         assertEquals("2", buttonCell.getText());
 991         assertEquals(2, sm.getSelectedIndex());
 992         
 993         sm.clearSelection();
 994         assertNull(sm.getSelectedItem());
 995         assertNull(comboBox.getValue());
 996         assertEquals("", buttonCell.getText());
 997         assertEquals(-1, sm.getSelectedIndex());
 998         
 999         sm.select("2");
1000         assertEquals("2", sm.getSelectedItem());
1001         assertEquals("2", comboBox.getValue());
1002         assertEquals("2", buttonCell.getText());
1003         assertEquals(2, sm.getSelectedIndex());
1004     }
1005     
1006     @Test public void test_rt28245() {
1007         final ObservableList<String> strings = FXCollections.observableArrayList(
1008             "Option 1", "Option 2", "Option 3"
1009         );
1010         
1011         ComboBox<String> comboBox = new ComboBox<String>();
1012         comboBox.setItems(strings);
1013         comboBox.setEditable(true);
1014         comboBox.valueProperty().addListener((ov, t, t1) -> {
1015             if (t == null && t1.isEmpty()) {
1016                 fail("Old value is '" + t + "' and new value is '" + t1 + "'.");
1017             }
1018         });
1019         
1020         StageLoader sl = new StageLoader(comboBox);
1021         
1022         assertNull(comboBox.getValue());
1023         assertTrue(comboBox.getEditor().getText().isEmpty());
1024         
1025         comboBox.requestFocus();
1026         
1027         new KeyEventFirer(comboBox).doKeyPress(KeyCode.ENTER);
1028 
1029         sl.dispose();
1030     }
1031 
1032     @Test public void test_rt31479() {
1033         ComboBox<String> comboBox = new ComboBox<String>();
1034 
1035         StageLoader sl = new StageLoader(comboBox);
1036 
1037         final double widthBefore = comboBox.getWidth();
1038 
1039         // add item
1040         comboBox.getItems().add("Option 1");
1041 
1042         // open and close combobox
1043         comboBox.show();
1044         comboBox.hide();
1045 
1046         // set a placeholder
1047         comboBox.setPlaceholder(new Circle(12, Color.RED));
1048 
1049         // remove item
1050         comboBox.getItems().clear();
1051 
1052         // fire pulse (this allows layout to cause the size to grow)
1053         Toolkit.getToolkit().firePulse();
1054 
1055         // test size
1056         assertEquals(widthBefore, comboBox.getWidth(), 0.00);
1057 
1058         sl.dispose();
1059     }
1060 
1061     @Test public void test_rt32139() {
1062         final ObservableList<String> items =
1063                 FXCollections.observableArrayList("Good value", "Bad value");
1064 
1065         final ComboBox<String> comboBox = new ComboBox<>(items);
1066         comboBox.getSelectionModel().select(0);
1067 
1068         comboBox.getSelectionModel().selectedIndexProperty().addListener((ov, oldIdx, newIdx) -> {
1069             if (newIdx.intValue() != 0) {
1070                 comboBox.getSelectionModel().select(0);
1071             }
1072         });
1073 
1074         StageLoader sl = new StageLoader(comboBox);
1075 
1076         try {
1077             comboBox.getSelectionModel().select(1);
1078         } catch (StackOverflowError e) {
1079             fail("Stack overflow should not happen here");
1080         }
1081 
1082         sl.dispose();
1083     }
1084 
1085     @Test public void test_rt21186() {
1086         final ComboBox<String> comboBox = new ComboBox<>();
1087         comboBox.setEditable(true);
1088 
1089         StageLoader sl = new StageLoader(comboBox);
1090 
1091         assertNull(comboBox.getTooltip());
1092         assertNull(comboBox.getEditor().getTooltip());
1093 
1094         Tooltip tooltip = new Tooltip("Tooltip");
1095         comboBox.setTooltip(tooltip);
1096         assertEquals(tooltip, comboBox.getTooltip());
1097         assertEquals(tooltip, comboBox.getEditor().getTooltip());
1098 
1099         comboBox.setTooltip(null);
1100         assertNull(comboBox.getTooltip());
1101         assertNull(comboBox.getEditor().getTooltip());
1102 
1103         sl.dispose();
1104     }
1105 
1106     @Test public void test_rt34573() {
1107         final ComboBox<String> comboBox = new ComboBox<>();
1108 
1109         final ListCell<String> customCell = new ListCell<String>() {
1110             @Override protected void updateItem(String item, boolean empty) {
1111                 super.updateItem(item, empty);
1112                 setText(item);
1113             }
1114         };
1115         comboBox.setButtonCell(customCell);
1116 
1117         StageLoader sl = new StageLoader(comboBox);
1118 
1119         comboBox.setItems(FXCollections.observableArrayList("A","B","C","D"));
1120         comboBox.setValue("B");
1121         assertEquals("B", comboBox.getButtonCell().getText());
1122         assertEquals(1, comboBox.getButtonCell().getIndex());
1123 
1124         comboBox.setItems(FXCollections.observableArrayList("1","2","3","4"));
1125         assertTrue(comboBox.getButtonCell().getText().isEmpty());
1126         assertEquals(-1, comboBox.getButtonCell().getIndex());
1127 
1128         sl.dispose();
1129     }
1130 
1131     @Test public void test_rt34566() {
1132         final ComboBox<String> comboBox = new ComboBox<>();
1133 
1134         final ListCell<String> customCell = new ListCell<String>() {
1135             @Override protected void updateItem(String item, boolean empty) {
1136                 super.updateItem(item, empty);
1137                 setText(item);
1138             }
1139         };
1140         comboBox.setButtonCell(customCell);
1141 
1142         StageLoader sl = new StageLoader(comboBox);
1143 
1144         comboBox.setItems(FXCollections.observableArrayList("A","B","C","D"));
1145 
1146         PseudoClass empty = PseudoClass.getPseudoClass("empty");
1147 
1148         comboBox.setValue("B");
1149         assertEquals("B", comboBox.getButtonCell().getText());
1150         assertEquals(1, comboBox.getButtonCell().getIndex());
1151         assertFalse(customCell.getPseudoClassStates().contains(empty));
1152 
1153         comboBox.setValue(null);
1154         Toolkit.getToolkit().firePulse();
1155         assertTrue(comboBox.getButtonCell().getText().isEmpty());
1156         assertEquals(-1, comboBox.getButtonCell().getIndex());
1157         assertTrue(customCell.getPseudoClassStates().contains(empty));
1158 
1159         comboBox.setValue("A");
1160         assertEquals("A", comboBox.getButtonCell().getText());
1161         assertEquals(0, comboBox.getButtonCell().getIndex());
1162         assertFalse(customCell.getPseudoClassStates().contains(empty));
1163 
1164         sl.dispose();
1165     }
1166 
1167     private int test_rt34603_count = 0;
1168     @Ignore("Bug has not yet been resolved")
1169     @Test public void test_rt34603() {
1170         assertEquals(0, test_rt34603_count);
1171 
1172         VBox hbox = new VBox(10);
1173 
1174         ComboBox<String> box = new ComboBox<>();
1175         box.getItems().add("test");
1176         box.setEditable(true);
1177         box.getSelectionModel().selectFirst();
1178 
1179         Button defaultButton = new Button("press");
1180         defaultButton.setOnAction(arg0 -> {
1181             test_rt34603_count++;
1182         });
1183         defaultButton.setDefaultButton(true);
1184 
1185         hbox.getChildren().addAll(box, defaultButton);
1186 
1187         StageLoader sl = new StageLoader(hbox);
1188 
1189         box.getEditor().requestFocus();
1190         KeyEventFirer keyboard = new KeyEventFirer(box);
1191         keyboard.doKeyPress(KeyCode.ENTER);
1192 
1193         assertEquals(1, test_rt34603_count);
1194 
1195         sl.dispose();
1196     }
1197 
1198     private int test_rt35586_count = 0;
1199     @Test public void test_rt35586() {
1200         assertEquals(0, test_rt34603_count);
1201 
1202         final ComboBox<String> cb = new ComboBox<String>();
1203         cb.setEditable(true);
1204         cb.setOnAction(event -> {
1205             test_rt35586_count++;
1206             assertEquals("Test", cb.getEditor().getText());
1207         });
1208 
1209         StageLoader sl = new StageLoader(cb);
1210 
1211         cb.getEditor().requestFocus();
1212         cb.getEditor().setText("Test");
1213         KeyEventFirer keyboard = new KeyEventFirer(cb.getEditor());
1214         keyboard.doKeyPress(KeyCode.ENTER);
1215 
1216         assertEquals(1, test_rt35586_count);
1217 
1218         sl.dispose();
1219     }
1220 
1221     @Test public void test_rt35039() {
1222         final List<String> data = new ArrayList<>();
1223         data.add("aabbaa");
1224         data.add("bbc");
1225 
1226         final ComboBox<String> combo = new ComboBox<>();
1227         combo.setEditable(true);
1228         combo.setItems(FXCollections.observableArrayList(data));
1229 
1230         StageLoader sl = new StageLoader(combo);
1231 
1232         // everything should be null to start with
1233         assertNull(combo.getValue());
1234         assertTrue(combo.getEditor().getText().isEmpty());
1235         assertNull(combo.getSelectionModel().getSelectedItem());
1236 
1237         // select "bbc" and ensure everything is set to that
1238         combo.getSelectionModel().select(1);
1239         assertEquals("bbc", combo.getValue());
1240         assertEquals("bbc", combo.getEditor().getText());
1241         assertEquals("bbc", combo.getSelectionModel().getSelectedItem());
1242 
1243         // change the items list - but retain the same content. We expect
1244         // that "bbc" remains selected as it is still in the list
1245         combo.setItems(FXCollections.observableArrayList(data));
1246         assertEquals("bbc", combo.getValue());
1247         assertEquals("bbc", combo.getEditor().getText());
1248         assertEquals("bbc", combo.getSelectionModel().getSelectedItem());
1249 
1250         sl.dispose();
1251     }
1252 
1253     @Test public void test_rt35840() {
1254         final ComboBox<String> cb = new ComboBox<String>();
1255         cb.setEditable(true);
1256         StageLoader sl = new StageLoader(cb);
1257         cb.requestFocus();
1258 
1259         KeyEventFirer keyboard = new KeyEventFirer(cb);
1260         keyboard.doKeyTyped(KeyCode.T);
1261         keyboard.doKeyTyped(KeyCode.E);
1262         keyboard.doKeyTyped(KeyCode.S);
1263         keyboard.doKeyTyped(KeyCode.T);
1264         assertEquals("TEST", cb.getEditor().getText());
1265 
1266         assertNull(cb.getValue());
1267         keyboard.doKeyPress(KeyCode.ENTER);
1268         assertEquals("TEST", cb.getValue());
1269 
1270         sl.dispose();
1271     }
1272 
1273     @Test public void test_rt36280_nonEditable_F4ShowsPopup() {
1274         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1275         StageLoader sl = new StageLoader(cb);
1276         KeyEventFirer cbKeyboard = new KeyEventFirer(cb);
1277 
1278         assertFalse(cb.isShowing());
1279         cbKeyboard.doKeyPress(KeyCode.F4);  // show the popup
1280         assertTrue(cb.isShowing());
1281 
1282         sl.dispose();
1283     }
1284 
1285     @Test public void test_rt36280_nonEditable_altUpShowsPopup() {
1286         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1287         StageLoader sl = new StageLoader(cb);
1288         KeyEventFirer cbKeyboard = new KeyEventFirer(cb);
1289 
1290         assertFalse(cb.isShowing());
1291         cbKeyboard.doKeyPress(KeyCode.UP, KeyModifier.ALT);  // show the popup
1292         assertTrue(cb.isShowing());
1293 
1294         sl.dispose();
1295     }
1296 
1297     @Test public void test_rt36280_nonEditable_altDownShowsPopup() {
1298         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1299         StageLoader sl = new StageLoader(cb);
1300         KeyEventFirer cbKeyboard = new KeyEventFirer(cb);
1301 
1302         new StageLoader(cb);
1303 
1304         assertFalse(cb.isShowing());
1305         cbKeyboard.doKeyPress(KeyCode.DOWN, KeyModifier.ALT);  // show the popup
1306         assertTrue(cb.isShowing());
1307 
1308         sl.dispose();
1309     }
1310 
1311     @Test public void test_rt36280_nonEditable_enterHidesShowingPopup() {
1312         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1313         StageLoader sl = new StageLoader(cb);
1314         KeyEventFirer cbKeyboard = new KeyEventFirer(cb);
1315 
1316         ListView listView = ((ComboBoxListViewSkin)cb.getSkin()).getListView();
1317         assertNotNull(listView);
1318 
1319         KeyEventFirer lvKeyboard = new KeyEventFirer(listView);
1320 
1321         assertFalse(cb.isShowing());
1322         cbKeyboard.doKeyPress(KeyCode.F4);  // show the popup
1323         assertTrue(cb.isShowing());
1324         lvKeyboard.doKeyPress(KeyCode.ENTER);  // hide the popup
1325         assertFalse(cb.isShowing());
1326 
1327         sl.dispose();
1328     }
1329 
1330     @Test public void test_rt36280_nonEditable_spaceHidesShowingPopup() {
1331         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1332         StageLoader sl = new StageLoader(cb);
1333         KeyEventFirer cbKeyboard = new KeyEventFirer(cb);
1334 
1335         ListView listView = ((ComboBoxListViewSkin)cb.getSkin()).getListView();
1336         assertNotNull(listView);
1337 
1338         KeyEventFirer lvKeyboard = new KeyEventFirer(listView);
1339 
1340         assertFalse(cb.isShowing());
1341         cbKeyboard.doKeyPress(KeyCode.F4);  // show the popup
1342         assertTrue(cb.isShowing());
1343         lvKeyboard.doKeyPress(KeyCode.SPACE);  // hide the popup
1344         assertFalse(cb.isShowing());
1345 
1346         sl.dispose();
1347     }
1348 
1349     @Test public void test_rt36280_nonEditable_escapeHidesShowingPopup() {
1350         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1351         StageLoader sl = new StageLoader(cb);
1352         KeyEventFirer cbKeyboard = new KeyEventFirer(cb);
1353 
1354         ListView listView = ((ComboBoxListViewSkin)cb.getSkin()).getListView();
1355         assertNotNull(listView);
1356 
1357         KeyEventFirer lvKeyboard = new KeyEventFirer(listView);
1358 
1359         assertFalse(cb.isShowing());
1360         cbKeyboard.doKeyPress(KeyCode.F4);  // show the popup
1361         assertTrue(cb.isShowing());
1362         lvKeyboard.doKeyPress(KeyCode.ESCAPE);  // hide the popup
1363         assertFalse(cb.isShowing());
1364 
1365         sl.dispose();
1366     }
1367 
1368     @Test public void test_rt36280_nonEditable_F4HidesShowingPopup() {
1369         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1370         StageLoader sl = new StageLoader(cb);
1371         KeyEventFirer cbKeyboard = new KeyEventFirer(cb);
1372 
1373         assertFalse(cb.isShowing());
1374         cbKeyboard.doKeyPress(KeyCode.F4);  // show the popup
1375         assertTrue(cb.isShowing());
1376         cbKeyboard.doKeyPress(KeyCode.F4);  // hide the popup
1377         assertFalse(cb.isShowing());
1378         
1379         sl.dispose();
1380     }
1381 
1382     @Test public void test_rt36280_nonEditable_arrowKeysChangeSelection() {
1383         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1384         StageLoader sl = new StageLoader(cb);
1385         KeyEventFirer cbKeyboard = new KeyEventFirer(cb);
1386 
1387         assertFalse(cb.isShowing());
1388         cbKeyboard.doKeyPress(KeyCode.F4);  // show the popup
1389         assertTrue(cb.isShowing());
1390 
1391         assertNull(cb.getSelectionModel().getSelectedItem());
1392 
1393         cbKeyboard.doDownArrowPress();
1394         assertEquals("a", cb.getSelectionModel().getSelectedItem());
1395 
1396         cbKeyboard.doDownArrowPress();
1397         assertEquals("b", cb.getSelectionModel().getSelectedItem());
1398 
1399         cbKeyboard.doUpArrowPress();
1400         assertEquals("a", cb.getSelectionModel().getSelectedItem());
1401 
1402         sl.dispose();
1403     }
1404 
1405     @Test public void test_rt36280_editable_F4ShowsPopup() {
1406         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1407         cb.setEditable(true);
1408         StageLoader sl = new StageLoader(cb);
1409         KeyEventFirer cbKeyboard = new KeyEventFirer(cb);
1410 
1411         assertFalse(cb.isShowing());
1412         cbKeyboard.doKeyPress(KeyCode.F4);  // show the popup
1413         assertTrue(cb.isShowing());
1414 
1415         sl.dispose();
1416     }
1417 
1418     @Test public void test_rt36280_editable_altUpShowsPopup() {
1419         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1420         cb.setEditable(true);
1421         StageLoader sl = new StageLoader(cb);
1422         KeyEventFirer cbKeyboard = new KeyEventFirer(cb);
1423 
1424         assertFalse(cb.isShowing());
1425         cbKeyboard.doKeyPress(KeyCode.UP, KeyModifier.ALT);  // show the popup
1426         assertTrue(cb.isShowing());
1427 
1428         sl.dispose();
1429     }
1430 
1431     @Test public void test_rt36280_editable_altDownShowsPopup_onComboBox() {
1432         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1433         cb.setEditable(true);
1434         StageLoader sl = new StageLoader(cb);
1435         KeyEventFirer cbKeyboard = new KeyEventFirer(cb);
1436 
1437         assertFalse(cb.isShowing());
1438         assertTrue(cb.getEditor().getText().isEmpty());
1439         cbKeyboard.doKeyPress(KeyCode.DOWN, KeyModifier.ALT);  // show the popup
1440         assertTrue(cb.isShowing());
1441         assertTrue(cb.getEditor().getText().isEmpty());
1442 
1443         sl.dispose();
1444     }
1445 
1446     @Test public void test_rt36280_editable_altDownShowsPopup_onTextField() {
1447         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1448         cb.setEditable(true);
1449         StageLoader sl = new StageLoader(cb);
1450 
1451         KeyEventFirer tfKeyboard = new KeyEventFirer(cb.getEditor());
1452         assertFalse(cb.isShowing());
1453         assertTrue(cb.getEditor().getText().isEmpty());
1454         tfKeyboard.doKeyPress(KeyCode.DOWN, KeyModifier.ALT);  // show the popup
1455         assertTrue(cb.isShowing());
1456         assertTrue(cb.getEditor().getText().isEmpty());
1457 
1458         sl.dispose();
1459     }
1460 
1461     @Test public void test_rt36280_editable_enterHidesShowingPopup() {
1462         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1463         cb.setEditable(true);
1464         StageLoader sl = new StageLoader(cb);
1465         KeyEventFirer cbKeyboard = new KeyEventFirer(cb);
1466 
1467         ListView listView = ((ComboBoxListViewSkin)cb.getSkin()).getListView();
1468         assertNotNull(listView);
1469 
1470         KeyEventFirer lvKeyboard = new KeyEventFirer(listView);
1471 
1472         assertFalse(cb.isShowing());
1473         cbKeyboard.doKeyPress(KeyCode.F4);  // show the popup
1474         assertTrue(cb.isShowing());
1475         lvKeyboard.doKeyPress(KeyCode.ENTER);  // hide the popup
1476         assertFalse(cb.isShowing());
1477 
1478         sl.dispose();
1479     }
1480 
1481     @Test public void test_rt36280_editable_spaceHidesShowingPopup() {
1482         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1483         cb.setEditable(true);
1484         StageLoader sl = new StageLoader(cb);
1485         KeyEventFirer cbKeyboard = new KeyEventFirer(cb);
1486 
1487         ListView listView = ((ComboBoxListViewSkin)cb.getSkin()).getListView();
1488         assertNotNull(listView);
1489 
1490         KeyEventFirer lvKeyboard = new KeyEventFirer(listView);
1491 
1492         assertFalse(cb.isShowing());
1493         cbKeyboard.doKeyPress(KeyCode.F4);  // show the popup
1494         assertTrue(cb.isShowing());
1495         lvKeyboard.doKeyPress(KeyCode.SPACE);  // hide the popup
1496         assertFalse(cb.isShowing());
1497 
1498         sl.dispose();
1499     }
1500 
1501     @Test public void test_rt36280_editable_escapeHidesShowingPopup() {
1502         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1503         cb.setEditable(true);
1504         StageLoader sl = new StageLoader(cb);
1505         KeyEventFirer cbKeyboard = new KeyEventFirer(cb);
1506 
1507         ListView listView = ((ComboBoxListViewSkin)cb.getSkin()).getListView();
1508         assertNotNull(listView);
1509 
1510         KeyEventFirer lvKeyboard = new KeyEventFirer(listView);
1511 
1512         assertFalse(cb.isShowing());
1513         cbKeyboard.doKeyPress(KeyCode.F4);  // show the popup
1514         assertTrue(cb.isShowing());
1515         lvKeyboard.doKeyPress(KeyCode.ESCAPE);  // hide the popup
1516         assertFalse(cb.isShowing());
1517 
1518         sl.dispose();
1519     }
1520 
1521     @Test public void test_rt36280_editable_F4HidesShowingPopup() {
1522         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1523         cb.setEditable(true);
1524         StageLoader sl = new StageLoader(cb);
1525         KeyEventFirer cbKeyboard = new KeyEventFirer(cb);
1526 
1527         assertFalse(cb.isShowing());
1528         cbKeyboard.doKeyPress(KeyCode.F4);  // show the popup
1529         assertTrue(cb.isShowing());
1530         cbKeyboard.doKeyPress(KeyCode.F4);  // hide the popup
1531         assertFalse(cb.isShowing());
1532 
1533         sl.dispose();
1534     }
1535 
1536     @Test public void test_rt36280_editable_arrowKeysChangeSelection() {
1537         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1538         cb.setEditable(true);
1539         StageLoader sl = new StageLoader(cb);
1540         KeyEventFirer cbKeyboard = new KeyEventFirer(cb);
1541 
1542         assertFalse(cb.isShowing());
1543         cbKeyboard.doKeyPress(KeyCode.F4);  // show the popup
1544         assertTrue(cb.isShowing());
1545 
1546         assertNull(cb.getSelectionModel().getSelectedItem());
1547 
1548         cbKeyboard.doDownArrowPress();
1549         assertEquals("a", cb.getSelectionModel().getSelectedItem());
1550 
1551         cbKeyboard.doDownArrowPress();
1552         assertEquals("b", cb.getSelectionModel().getSelectedItem());
1553 
1554         cbKeyboard.doUpArrowPress();
1555         assertEquals("a", cb.getSelectionModel().getSelectedItem());
1556         
1557         sl.dispose();
1558     }
1559 
1560     @Test public void test_rt36651() {
1561         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1562         cb.setEditable(true);
1563         StageLoader sl = new StageLoader(cb);
1564 
1565         assertNull(cb.getValue());
1566         assertEquals(-1, cb.getSelectionModel().getSelectedIndex());
1567         assertNull(cb.getSelectionModel().getSelectedItem());
1568 
1569         sl.getStage().requestFocus();
1570         cb.show();
1571         Toolkit.getToolkit().firePulse();
1572 
1573         // selection should not change just by showing the popup
1574         assertNull(cb.getValue());
1575         assertEquals(-1, cb.getSelectionModel().getSelectedIndex());
1576         assertNull(cb.getSelectionModel().getSelectedItem());
1577 
1578         sl.dispose();
1579     }
1580 
1581     @Test public void test_rt36717() {
1582         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1583         StageLoader sl = new StageLoader(cb);
1584 
1585         // the stack overflow only occurs when a ComboBox changes from non-editable to editable
1586         cb.setEditable(false);
1587         cb.setEditable(true);
1588         assertNotNull(cb.getEditor());
1589         KeyEventFirer tfKeyboard = new KeyEventFirer(cb.getEditor());
1590         tfKeyboard.doKeyPress(KeyCode.ENTER);   // Stack overflow here
1591 
1592         sl.dispose();
1593     }
1594 
1595     @Test public void test_rt36827() {
1596         final Button btn = new Button("focus owner");
1597         final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1598         VBox vbox = new VBox(btn, cb);
1599 
1600         StageLoader sl = new StageLoader(vbox);
1601         sl.getStage().requestFocus();
1602         btn.requestFocus();
1603         Toolkit.getToolkit().firePulse();
1604         Scene scene = sl.getStage().getScene();
1605 
1606         assertTrue(btn.isFocused());
1607         assertEquals(btn, scene.getFocusOwner());
1608 
1609         MouseEventFirer mouse = new MouseEventFirer(cb);
1610         mouse.fireMousePressAndRelease();
1611 
1612         assertTrue(cb.isShowing());
1613         assertTrue(cb.isFocused());
1614         assertEquals(cb, scene.getFocusOwner());
1615 
1616         sl.dispose();
1617     }
1618 
1619     @Ignore("fix not yet developed")
1620     @Test public void test_rt36902() {
1621         final ComboBox<String> cb1 = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1622         final ComboBox<String> cb2 = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
1623         cb2.setEditable(true);
1624         VBox vbox = new VBox(cb1, cb2);
1625 
1626         // lame - I would rather have one keyboard here but I couldn't get it to
1627         // work, so watch out for which keyboard is used below
1628         KeyEventFirer cb1Keyboard = new KeyEventFirer(cb1);
1629         KeyEventFirer cb2Keyboard = new KeyEventFirer(cb2);
1630 
1631         StageLoader sl = new StageLoader(vbox);
1632         sl.getStage().requestFocus();
1633         cb1.requestFocus();
1634         Toolkit.getToolkit().firePulse();
1635         Scene scene = sl.getStage().getScene();
1636 
1637         assertTrue(cb1.isFocused());
1638         assertEquals(cb1, scene.getFocusOwner());
1639 
1640         // move focus forward to cb2
1641         cb1Keyboard.doKeyPress(KeyCode.TAB);
1642         assertTrue(cb2.isFocused());
1643         assertEquals(cb2, scene.getFocusOwner());
1644 
1645         // move focus forward again to cb1
1646         cb2Keyboard.doKeyPress(KeyCode.TAB);
1647         assertTrue(cb1.isFocused());
1648         assertEquals(cb1, scene.getFocusOwner());
1649 
1650         // now start going backwards with shift-tab.
1651         // The first half of the bug is here - when we shift-tab into cb2, we
1652         // actually go into the FakeFocusTextField subcomponent, so whilst the
1653         // cb2.isFocused() returns true as expected, the scene focus owner is
1654         // not the ComboBox, but the FakeFocusTextField inside it
1655         cb1Keyboard.doKeyPress(KeyCode.TAB, KeyModifier.SHIFT);
1656         assertTrue("Expect cb2 to be focused, but actual focus owner is: " + scene.getFocusOwner(),
1657                 cb2.isFocused());
1658         assertEquals("Expect cb2 TextField to be focused, but actual focus owner is: " + scene.getFocusOwner(),
1659                 cb2.getEditor(), scene.getFocusOwner());
1660 
1661         // This is where the second half of the bug appears, as we are stuck in
1662         // the FakeFocusTextField of cb2, we never make it to cb1
1663         cb2Keyboard.doKeyPress(KeyCode.TAB, KeyModifier.SHIFT);
1664         assertTrue(cb1.isFocused());
1665         assertEquals(cb1, scene.getFocusOwner());
1666 
1667         sl.dispose();
1668     }
1669 
1670     private int rt_38901_counter;
1671     @Test public void test_rt_38901_selectNull() {
1672         test_rt_38901(true);
1673     }
1674 
1675     @Test public void test_rt_38901_selectNegativeOne() {
1676         test_rt_38901(false);
1677     }
1678 
1679     private void test_rt_38901(boolean selectNull) {
1680         rt_38901_counter = 0;
1681 
1682         final ComboBox<String> cb = new ComboBox<>();
1683         cb.setOnShowing((e) -> {
1684             cb.getItems().setAll("DUMMY " + (rt_38901_counter++));
1685         });
1686 
1687         assertEquals(-1, cb.getSelectionModel().getSelectedIndex());
1688         assertNull(cb.getSelectionModel().getSelectedItem());
1689         assertNull(cb.getValue());
1690         assertEquals(0, cb.getItems().size());
1691 
1692         // round one
1693         cb.show();
1694         assertEquals(1, cb.getItems().size());
1695         assertEquals("DUMMY 0", cb.getItems().get(0));
1696         cb.hide();
1697 
1698         cb.getSelectionModel().select(0);
1699         assertEquals(0, cb.getSelectionModel().getSelectedIndex());
1700         assertEquals("DUMMY 0", cb.getSelectionModel().getSelectedItem());
1701         assertEquals("DUMMY 0", cb.getValue());
1702 
1703         if (selectNull) cb.getSelectionModel().select(null);
1704         else cb.getSelectionModel().select(-1);
1705 
1706         assertEquals(-1, cb.getSelectionModel().getSelectedIndex());
1707         assertNull(cb.getSelectionModel().getSelectedItem());
1708         assertNull(cb.getValue());
1709 
1710 
1711         // round two
1712         cb.show();
1713         assertEquals(1, cb.getItems().size());
1714         assertEquals("DUMMY 1", cb.getItems().get(0));
1715         cb.hide();
1716 
1717         cb.getSelectionModel().select(0);
1718         assertEquals(0, cb.getSelectionModel().getSelectedIndex());
1719         assertEquals("DUMMY 1", cb.getSelectionModel().getSelectedItem());
1720         assertEquals("DUMMY 1", cb.getValue());
1721 
1722         if (selectNull) cb.getSelectionModel().select(null);
1723         else cb.getSelectionModel().select(-1);
1724 
1725         assertEquals(-1, cb.getSelectionModel().getSelectedIndex());
1726         assertNull(cb.getSelectionModel().getSelectedItem());
1727         assertNull(cb.getValue());
1728     }
1729 
1730     private int rt_22572_counter;
1731     @Test public void test_rt_22572() {
1732         rt_22572_counter = 0;
1733 
1734         final ComboBox<String> cb = new ComboBox<>();
1735         cb.setOnShowing((e) -> {
1736             cb.getItems().setAll("DUMMY " + (rt_22572_counter++));
1737         });
1738 
1739         StageLoader sl = new StageLoader(cb);
1740 
1741         assertEquals(-1, cb.getSelectionModel().getSelectedIndex());
1742         assertNull(cb.getSelectionModel().getSelectedItem());
1743         assertNull(cb.getValue());
1744         assertEquals(0, cb.getItems().size());
1745 
1746         // round one
1747         cb.show();
1748         assertEquals(1, cb.getItems().size());
1749         assertEquals("DUMMY 0", cb.getItems().get(0));
1750         cb.hide();
1751 
1752         cb.getSelectionModel().select(0);
1753         assertEquals(0, cb.getSelectionModel().getSelectedIndex());
1754         assertEquals("DUMMY 0", cb.getSelectionModel().getSelectedItem());
1755         assertEquals("DUMMY 0", cb.getValue());
1756 
1757 
1758         // round two - even though the items change, the value should still be
1759         // the old value (even though it doesn't exist in the items list any longer).
1760         // The selectedIndex and selectedItem do get reset however.
1761         cb.show();
1762         assertEquals(1, cb.getItems().size());
1763         assertEquals("DUMMY 1", cb.getItems().get(0));
1764         cb.hide();
1765 
1766         assertEquals(-1, cb.getSelectionModel().getSelectedIndex());
1767         assertNull(cb.getSelectionModel().getSelectedItem());
1768         assertEquals("DUMMY 0", cb.getValue());
1769 
1770         sl.dispose();
1771     }
1772 
1773     private int rt_22937_counter;
1774     @Test public void test_rt_22937() {
1775         rt_22937_counter = 0;
1776 
1777         final ComboBox<String> cb = new ComboBox<>();
1778         cb.setOnShowing((e) -> {
1779             cb.getItems().setAll("DUMMY " + (rt_22937_counter++));
1780         });
1781 
1782         cb.getItems().add("Toto");
1783         cb.setEditable(true);
1784         cb.setValue("Tata");
1785 
1786         StageLoader sl = new StageLoader(cb);
1787 
1788         assertEquals(-1, cb.getSelectionModel().getSelectedIndex());
1789         assertEquals("Tata", cb.getSelectionModel().getSelectedItem());
1790         assertEquals("Tata", cb.getValue());
1791         assertEquals(1, cb.getItems().size());
1792 
1793         cb.show();
1794         assertEquals(1, cb.getItems().size());
1795         assertEquals("DUMMY 0", cb.getItems().get(0));
1796         cb.hide();
1797 
1798         cb.getSelectionModel().select(0);
1799         assertEquals(0, cb.getSelectionModel().getSelectedIndex());
1800         assertEquals("DUMMY 0", cb.getSelectionModel().getSelectedItem());
1801         assertEquals("DUMMY 0", cb.getValue());
1802 
1803         sl.dispose();
1804     }
1805 
1806     @Test public void test_rt_39809() {
1807         ComboBox<String> comboBox = new ComboBox<>();
1808         comboBox.getItems().setAll(null, "1", "2", "3");
1809 
1810         StageLoader sl = new StageLoader(comboBox);
1811 
1812         comboBox.getSelectionModel().clearAndSelect(1);
1813         assertEquals("1", comboBox.getSelectionModel().getSelectedItem());
1814         assertEquals(1, comboBox.getSelectionModel().getSelectedIndex());
1815 
1816         comboBox.getSelectionModel().clearAndSelect(0);
1817         assertEquals(null, comboBox.getSelectionModel().getSelectedItem());
1818         assertEquals(-1, comboBox.getSelectionModel().getSelectedIndex());
1819 
1820         sl.dispose();
1821     }
1822 
1823     @Test public void test_rt_39908() {
1824         ObservableList<String> model = FXCollections.observableArrayList("0", "1", "2", "3");
1825         ComboBox<String> comboBox = new ComboBox<>(model);
1826 
1827         StageLoader sl = new StageLoader(comboBox);
1828 
1829         comboBox.getSelectionModel().clearAndSelect(1);
1830         assertEquals("1", comboBox.getSelectionModel().getSelectedItem());
1831         assertEquals(1, comboBox.getSelectionModel().getSelectedIndex());
1832 
1833         model.set(0, "a");
1834         assertEquals("1", comboBox.getSelectionModel().getSelectedItem());
1835         assertEquals(1, comboBox.getSelectionModel().getSelectedIndex());
1836 
1837         sl.dispose();
1838     }
1839 
1840     /**
1841      * Bullet 1: selected index must be updated
1842      * Corner case: last selected. Fails for core
1843      */
1844     @Test public void test_rt_40012_selectedAtLastOnDisjointRemoveItemsAbove() {
1845         ObservableList<String> items = FXCollections.observableArrayList("0", "1", "2", "3", "4", "5");
1846         ComboBox<String> comboBox = new ComboBox<>(items);
1847         SelectionModel sm = comboBox.getSelectionModel();
1848 
1849         int last = items.size() - 1;
1850 
1851         // selecting item "5"
1852         sm.select(last);
1853 
1854         // disjoint remove of 2 elements above the last selected
1855         // Removing "1" and "3"
1856         items.removeAll(items.get(1), items.get(3));
1857 
1858         // selection should move up two places such that it remains on item "5",
1859         // but in index (last - 2).
1860         int expected = last - 2;
1861         assertEquals("5", sm.getSelectedItem());
1862         assertEquals("selected index after disjoint removes above", expected, sm.getSelectedIndex());
1863     }
1864 
1865     /**
1866      * Variant of 1: if selectedIndex is not updated,
1867      * the old index is no longer valid
1868      * for accessing the items.
1869      */
1870     @Test public void test_rt_40012_accessSelectedAtLastOnDisjointRemoveItemsAbove() {
1871         ObservableList<String> items = FXCollections.observableArrayList("0", "1", "2", "3", "4", "5");
1872         ComboBox<String> comboBox = new ComboBox<>(items);
1873         SelectionModel sm = comboBox.getSelectionModel();
1874 
1875         int last = items.size() - 1;
1876 
1877         // selecting item "5"
1878         sm.select(last);
1879 
1880         // disjoint remove of 2 elements above the last selected
1881         items.removeAll(items.get(1), items.get(3));
1882         int selected = sm.getSelectedIndex();
1883         if (selected > -1) {
1884             items.get(selected);
1885         }
1886     }
1887 
1888     /**
1889      * Bullet 2: selectedIndex notification count
1890      *
1891      * Note that we don't use the corner case of having the last index selected
1892      * (which fails already on updating the index)
1893      */
1894     private int rt_40012_count = 0;
1895     @Test public void test_rt_40012_selectedIndexNotificationOnDisjointRemovesAbove() {
1896         ObservableList<String> items = FXCollections.observableArrayList("0", "1", "2", "3", "4", "5");
1897         ComboBox<String> comboBox = new ComboBox<>(items);
1898         SelectionModel sm = comboBox.getSelectionModel();
1899 
1900         int last = items.size() - 2;
1901         sm.select(last);
1902         assertEquals(last, sm.getSelectedIndex());
1903 
1904         rt_40012_count = 0;
1905         sm.selectedIndexProperty().addListener(o -> rt_40012_count++);
1906 
1907         // disjoint remove of 2 elements above the last selected
1908         items.removeAll(items.get(1), items.get(3));
1909         assertEquals("sanity: selectedIndex must be shifted by -2", last - 2, sm.getSelectedIndex());
1910         assertEquals("must fire single event on removes above", 1, rt_40012_count);
1911     }
1912 
1913     /**
1914      * Bullet 3: unchanged selectedItem must not fire change
1915      */
1916     @Test
1917     public void test_rt_40012_selectedItemNotificationOnDisjointRemovesAbove() {
1918         ObservableList<String> items = FXCollections.observableArrayList("0", "1", "2", "3", "4", "5");
1919         ComboBox<String> comboBox = new ComboBox<>(items);
1920         SelectionModel sm = comboBox.getSelectionModel();
1921 
1922         int last = items.size() - 2;
1923         Object lastItem = items.get(last);
1924         sm.select(last);
1925         assertEquals(lastItem, sm.getSelectedItem());
1926 
1927         rt_40012_count = 0;
1928         sm.selectedItemProperty().addListener(o -> rt_40012_count++);
1929 
1930         // disjoint remove of 2 elements above the last selected
1931         items.removeAll(items.get(1), items.get(3));
1932         assertEquals("sanity: selectedItem unchanged", lastItem, sm.getSelectedItem());
1933         assertEquals("must not fire on unchanged selected item", 0, rt_40012_count);
1934     }
1935 }