1 /*
   2  * Copyright (c) 2011, 2014, 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 test.com.sun.javafx.pgstub.StubToolkit;
  29 import com.sun.javafx.tk.Toolkit;
  30 
  31 import static com.sun.javafx.scene.control.infrastructure.ControlTestUtils.assertPseudoClassDoesNotExist;
  32 import static com.sun.javafx.scene.control.infrastructure.ControlTestUtils.assertPseudoClassExists;
  33 import static com.sun.javafx.scene.control.infrastructure.ControlTestUtils.assertStyleClassContains;
  34 import javafx.scene.control.skin.ChoiceBoxSkin;
  35 import javafx.scene.control.skin.ChoiceBoxSkinNodesRetriever;
  36 import javafx.application.Platform;
  37 import static org.junit.Assert.assertEquals;
  38 import static org.junit.Assert.assertFalse;
  39 import static org.junit.Assert.assertNotNull;
  40 import static org.junit.Assert.assertNull;
  41 import static org.junit.Assert.assertSame;
  42 import static org.junit.Assert.assertTrue;
  43 import javafx.beans.property.ObjectProperty;
  44 import javafx.beans.property.SimpleObjectProperty;
  45 import javafx.beans.property.SimpleStringProperty;
  46 import javafx.beans.property.StringProperty;
  47 import javafx.collections.FXCollections;
  48 import javafx.collections.ObservableList;
  49 import javafx.scene.Parent;
  50 import javafx.scene.Scene;
  51 import javafx.scene.layout.StackPane;
  52 import javafx.stage.Stage;
  53 
  54 import org.junit.Before;
  55 import org.junit.Ignore;
  56 import org.junit.Test;
  57 
  58 public class ChoiceBoxTest {
  59     private final ChoiceBox<String> box = new ChoiceBox<String>();
  60     private Toolkit tk;
  61     private Scene scene;
  62     private Stage stage;
  63     
  64     @Before public void setup() {
  65         //This step is not needed (Just to make sure StubToolkit is loaded into VM)
  66         tk = (StubToolkit)Toolkit.getToolkit();
  67     }
  68     
  69     protected void startApp(Parent root) {
  70         scene = new Scene(root,800,600);
  71         stage = new Stage();
  72         stage.setScene(scene);
  73         stage.show();
  74         tk.firePulse();
  75     }
  76     
  77     /*********************************************************************
  78      * Tests for the constructors                                        *
  79      ********************************************************************/
  80     
  81     @Test public void noArgConstructorSetsTheStyleClass() {
  82         assertStyleClassContains(box, "choice-box");
  83     }
  84     
  85     @Test public void noArgConstructorSetsNonNullSelectionModel() {
  86         assertNotNull(box.getSelectionModel());
  87     }
  88     
  89     @Test public void noArgConstructorSetsNonNullItems() {
  90         assertNotNull(box.getItems());
  91     }
  92     
  93     @Test public void noArgConstructor_selectedItemIsNull() {
  94         assertNull(box.getSelectionModel().getSelectedItem());
  95     }
  96     
  97     @Test public void noArgConstructor_selectedIndexIsNegativeOne() {
  98         assertEquals(-1, box.getSelectionModel().getSelectedIndex());
  99     }
 100     @Test public void noArgConstructor_converterIsNotNull() {
 101         assertNull(box.getConverter());
 102     }
 103     
 104     @Test public void singleArgConstructorSetsTheStyleClass() {
 105         final ChoiceBox<String> b2 = new ChoiceBox<String>(FXCollections.observableArrayList("Hi"));
 106         assertStyleClassContains(b2, "choice-box");
 107     }
 108     
 109     @Test public void singleArgConstructorSetsNonNullSelectionModel() {
 110         final ChoiceBox<String> b2 = new ChoiceBox<String>(FXCollections.observableArrayList("Hi"));
 111         assertNotNull(b2.getSelectionModel());
 112     }
 113     
 114     @Test public void singleArgConstructorAllowsNullItems() {
 115         final ChoiceBox<String> b2 = new ChoiceBox<String>(null);
 116         assertNull(b2.getItems());
 117     }
 118     
 119     @Test public void singleArgConstructorTakesItems() {
 120         ObservableList<String> items = FXCollections.observableArrayList("Hi");
 121         final ChoiceBox<String> b2 = new ChoiceBox<String>(items);
 122         assertSame(items, b2.getItems());
 123     }
 124     
 125     @Test public void singleArgConstructor_selectedItemIsNull() {
 126         final ChoiceBox<String> b2 = new ChoiceBox<String>(FXCollections.observableArrayList("Hi"));
 127         assertNull(b2.getSelectionModel().getSelectedItem());
 128     }
 129     
 130     @Test public void singleArgConstructor_selectedIndexIsNegativeOne() {
 131         final ChoiceBox<String> b2 = new ChoiceBox<String>(FXCollections.observableArrayList("Hi"));
 132         assertEquals(-1, b2.getSelectionModel().getSelectedIndex());
 133     }
 134     
 135     @Test public void singleArgConstructor_converterIsNotNull() {
 136         final ChoiceBox<String> b2 = new ChoiceBox<String>(FXCollections.observableArrayList("Hi"));
 137         assertNull(b2.getConverter());
 138     }
 139     
 140     /*********************************************************************
 141      * Tests for selection model                                         *
 142      ********************************************************************/
 143     
 144     @Test public void selectionModelCanBeNull() {
 145         box.setSelectionModel(null);
 146         assertNull(box.getSelectionModel());
 147     }
 148 
 149     @Test public void selectionModelCanBeBound() {
 150         SingleSelectionModel<String> sm = new ChoiceBox.ChoiceBoxSelectionModel<String>(box);
 151         ObjectProperty<SingleSelectionModel<String>> other = new SimpleObjectProperty<SingleSelectionModel<String>>(sm);
 152         box.selectionModelProperty().bind(other);
 153         assertSame(sm, box.getSelectionModel());
 154     }
 155 
 156     @Test public void selectionModelCanBeChanged() {
 157         SingleSelectionModel<String> sm = new ChoiceBox.ChoiceBoxSelectionModel<String>(box);
 158         box.setSelectionModel(sm);
 159         assertSame(sm, box.getSelectionModel());
 160     }
 161     
 162     @Test public void canSetSelectedItemToAnItemEvenWhenThereAreNoItems() {
 163         final String randomString = new String("I AM A CRAZY RANDOM STRING");
 164         box.getSelectionModel().select(randomString);
 165         assertEquals(-1, box.getSelectionModel().getSelectedIndex());
 166         assertSame(randomString, box.getSelectionModel().getSelectedItem());
 167     }
 168         
 169     @Test public void canSetSelectedItemToAnItemNotInTheChoiceBoxItems() {
 170         box.getItems().addAll("Apple", "Orange", "Banana");
 171         final String randomString = new String("I AM A CRAZY RANDOM STRING");
 172         box.getSelectionModel().select(randomString);
 173         assertEquals(-1, box.getSelectionModel().getSelectedIndex());
 174         assertSame(randomString, box.getSelectionModel().getSelectedItem());
 175     }
 176         
 177     @Test public void settingTheSelectedItemToAnItemInItemsResultsInTheCorrectSelectedIndex() {
 178         box.getItems().addAll("Apple", "Orange", "Banana");
 179         box.getSelectionModel().select("Orange");
 180         assertEquals(1, box.getSelectionModel().getSelectedIndex());
 181         assertSame("Orange", box.getSelectionModel().getSelectedItem());
 182     }
 183     
 184     @Test public void settingTheSelectedItemToANonexistantItemAndThenAddingItemsWhichContainsItResultsInCorrectSelectedIndex() {
 185         box.getSelectionModel().select("Orange");
 186         box.getItems().addAll("Apple", "Orange", "Banana");
 187         assertEquals(1, box.getSelectionModel().getSelectedIndex());
 188         assertSame("Orange", box.getSelectionModel().getSelectedItem());
 189     }
 190 
 191     @Test public void settingTheSelectedItemToANonexistantItemAndThenSettingItemsWhichContainsItResultsInCorrectSelectedIndex() {
 192         box.getSelectionModel().select("Orange");
 193         box.getItems().setAll("Apple", "Orange", "Banana");
 194         assertEquals(1, box.getSelectionModel().getSelectedIndex());
 195         assertSame("Orange", box.getSelectionModel().getSelectedItem());
 196     }
 197     
 198     @Test public void ensureSelectionClearsWhenAllItemsAreRemoved_selectIndex0() {
 199         box.getItems().addAll("Apple", "Orange", "Banana");
 200         box.getSelectionModel().select(0);
 201         box.getItems().clear();
 202         assertEquals(-1, box.getSelectionModel().getSelectedIndex());
 203         assertEquals(null, box.getSelectionModel().getSelectedItem());
 204     }
 205 
 206     @Test public void ensureSelectionClearsWhenSettingSelectionBeforePopulatingItemsAndAllItemsAreRemoved() {
 207         box.getSelectionModel().select("Banana");
 208         box.getItems().addAll("Apple", "Orange", "Banana");
 209         box.getItems().clear();
 210         assertEquals(-1, box.getSelectionModel().getSelectedIndex());
 211         assertEquals(null, box.getSelectionModel().getSelectedItem());
 212     }
 213 
 214     @Ignore
 215     @Test public void ensureSelectionClearsWhenSettingSelectionBeforePopulatingItemsAndSelectedItemIsRemoved() {
 216         box.getSelectionModel().select("Banana");
 217         box.getItems().addAll("Apple", "Orange", "Banana");
 218         box.getItems().remove("Banana");
 219         assertEquals(-1, box.getSelectionModel().getSelectedIndex());
 220         assertEquals(null, box.getSelectionModel().getSelectedItem());
 221     }
 222 
 223     @Test public void ensureSelectionClearsWhenAllItemsAreRemoved_selectIndex2() {
 224         box.getItems().addAll("Apple", "Orange", "Banana");
 225         box.getSelectionModel().select(2);
 226         box.getItems().clear();
 227         assertEquals(-1, box.getSelectionModel().getSelectedIndex());
 228         assertEquals(null, box.getSelectionModel().getSelectedItem());
 229     }
 230     
 231     @Test public void ensureSelectedItemRemainsAccurateWhenItemsAreCleared() {
 232         box.getItems().addAll("Apple", "Orange", "Banana");
 233         box.getSelectionModel().select(2);
 234         box.getItems().clear();
 235         assertNull(box.getSelectionModel().getSelectedItem());
 236         assertEquals(-1, box.getSelectionModel().getSelectedIndex());
 237         
 238         box.getItems().addAll("Kiwifruit", "Mandarin", "Pineapple");
 239         box.getSelectionModel().select(2);
 240         assertEquals("Pineapple", box.getSelectionModel().getSelectedItem());
 241     }
 242     
 243     @Test public void ensureSelectionIsCorrectWhenItemsChange() {
 244         box.setItems(FXCollections.observableArrayList("Item 1"));
 245         box.getSelectionModel().select(0);
 246         assertEquals("Item 1", box.getSelectionModel().getSelectedItem());
 247         
 248         box.setItems(FXCollections.observableArrayList("Item 2"));
 249         assertEquals(-1, box.getSelectionModel().getSelectedIndex());
 250         assertEquals(null, box.getSelectionModel().getSelectedItem());
 251     }
 252     
 253     @Test public void ensureSelectionModelUpdatesValueProperty_withSelectIndex() {
 254         box.getItems().addAll("Apple", "Orange", "Banana");
 255         assertNull(box.getValue());
 256         box.getSelectionModel().select(0);
 257         assertEquals("Apple", box.getValue());
 258     }
 259     
 260     @Test public void ensureSelectionModelUpdatesValueProperty_withSelectItem() {
 261         box.getItems().addAll("Apple", "Orange", "Banana");
 262         assertNull(box.getValue());
 263         box.getSelectionModel().select("Apple");
 264         assertEquals("Apple", box.getValue());
 265     }
 266     
 267     @Test public void ensureSelectionModelUpdatesValueProperty_withSelectPrevious() {
 268         box.getItems().addAll("Apple", "Orange", "Banana");
 269         assertNull(box.getValue());
 270         box.getSelectionModel().select(2);
 271         box.getSelectionModel().selectPrevious();
 272         assertEquals("Orange", box.getValue());
 273     }
 274     
 275     @Test public void ensureSelectionModelUpdatesValueProperty_withSelectNext() {
 276         box.getItems().addAll("Apple", "Orange", "Banana");
 277         assertNull(box.getValue());
 278         box.getSelectionModel().select("Orange");
 279         box.getSelectionModel().selectNext();
 280         assertEquals("Banana", box.getValue());
 281     }
 282     
 283     @Test public void ensureSelectionModelUpdatesValueProperty_withSelectFirst() {
 284         box.getItems().addAll("Apple", "Orange", "Banana");
 285         assertNull(box.getValue());
 286         box.getSelectionModel().selectFirst();
 287         assertEquals("Apple", box.getValue());
 288     }
 289     
 290     @Test public void ensureSelectionModelUpdatesValueProperty_withSelectLast() {
 291         box.getItems().addAll("Apple", "Orange", "Banana");
 292         assertNull(box.getValue());
 293         box.getSelectionModel().selectLast();
 294         assertEquals("Banana", box.getValue());
 295     }
 296     
 297     @Test public void ensureSelectionModelClearsValueProperty() {
 298         box.getItems().addAll("Apple", "Orange", "Banana");
 299         assertNull(box.getValue());
 300         box.getSelectionModel().select(0);
 301         assertEquals("Apple", box.getValue());
 302         
 303         box.getSelectionModel().clearSelection();
 304         assertNull(box.getValue());
 305     }
 306     
 307     @Test public void ensureSelectionModelClearsValuePropertyWhenNegativeOneSelected() {
 308         box.getItems().addAll("Apple", "Orange", "Banana");
 309         assertNull(box.getValue());
 310         box.getSelectionModel().select(0);
 311         assertEquals("Apple", box.getValue());
 312         
 313         box.getSelectionModel().select(-1);
 314         assertEquals(null, box.getValue());
 315     }
 316     
 317     @Test public void ensureValueIsCorrectWhenItemsIsAddedToWithExistingSelection() {
 318         box.getItems().addAll("Apple", "Orange", "Banana");
 319         box.getSelectionModel().select(1);
 320         box.getItems().add(0, "pineapple");
 321         assertEquals(2, box.getSelectionModel().getSelectedIndex());
 322         assertEquals("Orange", box.getSelectionModel().getSelectedItem());
 323         assertEquals("Orange", box.getValue());
 324     }
 325     
 326     @Test public void ensureValueIsCorrectWhenItemsAreRemovedWithExistingSelection() {
 327         box.getItems().addAll("Apple", "Orange", "Banana");
 328         box.getSelectionModel().select(1);
 329         
 330         box.getItems().remove("Apple");
 331         
 332         assertEquals(0, box.getSelectionModel().getSelectedIndex());
 333         assertEquals("Orange", box.getSelectionModel().getSelectedItem());
 334         assertEquals("Orange", box.getValue());
 335     }
 336     
 337     @Test public void ensureValueIsUpdatedByCorrectSelectionModelWhenSelectionModelIsChanged() {
 338         box.getItems().addAll("Apple", "Orange", "Banana");
 339         SelectionModel sm1 = box.getSelectionModel();
 340         sm1.select(1);
 341         assertEquals("Orange", box.getValue());
 342         SingleSelectionModel sm2 = new ChoiceBox.ChoiceBoxSelectionModel(box);
 343         box.setSelectionModel(sm2);
 344         
 345         sm1.select(2);  // value should not change as we are using old SM
 346         assertEquals("Orange", box.getValue());
 347         
 348         sm2.select(0);  // value should change, as we are using new SM
 349         assertEquals("Apple", box.getValue());
 350     }
 351     
 352     @Test public void ensureValueDoesNotChangeWhenBoundAndNoExceptions() {
 353         box.getItems().addAll("Apple", "Orange", "Banana");
 354         
 355         StringProperty sp = new SimpleStringProperty("empty");
 356         box.valueProperty().bind(sp);
 357         
 358         box.getSelectionModel().select(1);
 359         assertEquals("empty", box.getValue());
 360     }
 361     
 362     @Test public void ensureSelectionModelUpdatesWhenValueChanges() {
 363         box.getItems().addAll("Apple", "Orange", "Banana");
 364         assertNull(box.getSelectionModel().getSelectedItem());
 365         box.setValue("Orange");
 366         assertEquals("Orange", box.getSelectionModel().getSelectedItem());
 367     }
 368     
 369     @Test public void ensureValueEqualsSelectedItemWhenNotInItemsList() {
 370         box.getItems().addAll("Apple", "Orange", "Banana");
 371         box.getSelectionModel().setSelectedItem("pineapple");
 372         assertEquals("pineapple", box.getSelectionModel().getSelectedItem());
 373         assertEquals("pineapple", box.getValue());
 374     }
 375     
 376     @Test public void ensureSelectionModelUpdatesWhenValueChangesToNull() {
 377         box.getItems().addAll("Apple", "Orange", "Banana");
 378         box.setValue("pineapple");
 379         assertEquals("pineapple", box.getSelectionModel().getSelectedItem());
 380         assertEquals("pineapple", box.getValue());
 381         box.setValue(null);
 382         assertEquals(null, box.getSelectionModel().getSelectedItem());
 383         assertEquals(-1, box.getSelectionModel().getSelectedIndex());
 384         assertEquals(null, box.getValue());
 385     }
 386     
 387     /*********************************************************************
 388      * Tests for showing property                                        *
 389      ********************************************************************/
 390     
 391     @Test public void showingIsFalseByDefault() {
 392         assertFalse(box.isShowing());
 393     }
 394     
 395     @Test public void showingCanBeSet() {
 396         box.show();
 397         assertTrue(box.isShowing());
 398     }
 399     
 400     @Test public void showingCanBeCleared() {
 401         box.show();
 402         box.hide();
 403         assertFalse(box.isShowing());
 404     }
 405     
 406     @Test public void showDoesntWorkWhenDisabled() {
 407         box.setDisable(true);
 408         box.show();
 409         assertFalse(box.isShowing());
 410     }
 411     
 412     @Ignore("impl_cssSet API removed")
 413     @Test public void cannotSpecifyShowingViaCSS() {
 414 //        box.impl_cssSet("-fx-showing", true);
 415         assertFalse(box.isShowing());
 416     }
 417     
 418     @Test public void settingShowingSetsPseudoClass() {
 419         box.show();
 420         assertPseudoClassExists(box, "showing");
 421     }
 422     
 423     @Test public void clearingArmedClearsPseudoClass() {
 424         box.show();
 425         box.hide();
 426         assertPseudoClassDoesNotExist(box, "showing");
 427     }
 428     
 429     @Test public void testAddingEmptyChoiceBoxToLiveScene() {
 430         StackPane pane = new StackPane();
 431         pane.getChildren().add(box);
 432         startApp(pane);
 433         assertEquals(0, box.getItems().size());
 434     }
 435     
 436      @Test public void testSelectingItemBeforeFirstShow() {
 437         StackPane pane = new StackPane();
 438         pane.getChildren().add(box);
 439         box.getItems().addAll("Apple", "Orange", "Banana");
 440         box.getSelectionModel().select("Orange");
 441         startApp(pane);
 442         assertEquals(1, box.getSelectionModel().getSelectedIndex());
 443     }
 444      
 445     @Test public void checkLabelAfterCallingSetItemsFromPlatformRunLater_RT30317() {
 446         final String[] items = {"Apple", "Orange", "Banana"};
 447         StackPane pane = new StackPane();
 448         pane.getChildren().add(box);
 449         Runnable runnable = () -> {
 450             box.setItems(FXCollections.observableArrayList(items));
 451             box.getSelectionModel().setSelectedItem("Apple");
 452         };
 453         Platform.runLater(runnable); 
 454         startApp(pane);
 455         assertEquals(0, box.getSelectionModel().getSelectedIndex());
 456         ChoiceBoxSkin skin = (ChoiceBoxSkin)box.getSkin();
 457         assertEquals("Apple", ChoiceBoxSkinNodesRetriever.getChoiceBoxSelectedText(skin));
 458         
 459     }
 460     
 461     @Test public void checkSelectedItemAfterReplacingDataWithEmptyList() {
 462         StackPane pane = new StackPane();
 463         pane.getChildren().add(box);
 464         box.getItems().addAll("Apple", "Orange", "Banana");
 465         box.getSelectionModel().select("Orange");
 466         startApp(pane);
 467         box.getItems().clear();
 468         // make sure the selected item is null
 469         assertEquals(null, box.getSelectionModel().getSelectedItem());
 470     }
 471 }