/******************************************************************************* * Mission Control Technologies, Copyright (c) 2009-2012, United States Government * as represented by the Administrator of the National Aeronautics and Space * Administration. All rights reserved. * * The MCT platform is licensed under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * MCT includes source code licensed under additional open source licenses. See * the MCT Open Source Licenses file included with this distribution or the About * MCT Licenses dialog available at runtime from the MCT Help menu for additional * information. *******************************************************************************/ package gov.nasa.arc.mct.defaults.view; import gov.nasa.arc.mct.components.AbstractComponent; import gov.nasa.arc.mct.gui.View; import gov.nasa.arc.mct.gui.ViewProvider; import gov.nasa.arc.mct.services.component.ViewInfo; import gov.nasa.arc.mct.services.component.ViewType; import java.awt.Component; import java.awt.Container; import java.awt.Graphics; import java.util.Collections; import java.util.Comparator; import java.util.Set; import java.util.TreeSet; import javax.swing.Icon; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.plaf.ComboBoxUI; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class TestSwitcherView { @Mock ViewProvider mockViewProvider; @Mock ViewInfo mockViewInfo1; @Mock ViewInfo mockViewInfo2; @Mock Icon mockIcon; @Mock AbstractComponent mockComponent; @BeforeMethod public void beforeMethod() { MockitoAnnotations.initMocks(this); @SuppressWarnings("serial") View view = new View(mockComponent, mockViewInfo1) {}; Mockito.when(mockViewProvider.getHousedViewManifestation()) .thenReturn(view); // Enforce desired test order of view infos, such that mockViewInfo1 is selected by default Set<ViewInfo> mockViewInfos = new TreeSet<ViewInfo>(new Comparator<ViewInfo>() { @Override public int compare(ViewInfo o1, ViewInfo o2) { return (o1.equals(o2)) ? 0 : ((o1 == mockViewInfo1) ? -1 : 1); } }); mockViewInfos.add(mockViewInfo1); mockViewInfos.add(mockViewInfo2); Mockito.when(mockComponent.getViewInfos(ViewType.OBJECT)) .thenReturn(mockViewInfos); } @Test (dataProvider = "generateSwitcherTests") public void testSwitcher(boolean addGUI, boolean doChange, boolean acceptChange) { // Create the test object View switcherView = SwitcherView.VIEW_INFO.createView(mockComponent); // Act as though the view provider has/hasn't accepted the view switch Mockito.when(mockViewProvider.setHousedViewManifestation(mockViewInfo2)) .thenReturn(acceptChange); // Attach view provider to gui, if this test iteration says we should if (addGUI) { switcherView.addMonitoredGUI(mockViewProvider); } // Find combo box so we can change selection @SuppressWarnings("rawtypes") JComboBox comboBox = findComponent(switcherView, JComboBox.class); Assert.assertNotNull(comboBox); // Change the item - again, only if we're supposed to if (doChange) { comboBox.setSelectedItem(mockViewInfo2); } // Verify that the change was reported to the GUI, // if a GUI was attached and the change was done Mockito.verify(mockViewProvider, Mockito.times(addGUI && doChange ? 1 : 0)) .setHousedViewManifestation(mockViewInfo2); // Verify that combo box state has/hasn't reset, as apparopriate // Specifically, only should if change was done, and an attached GUI didn't reject it boolean shouldChange = doChange && !(addGUI && !acceptChange); Assert.assertEquals(comboBox.getSelectedItem(), shouldChange ? mockViewInfo2 : mockViewInfo1); } @Test public void testViewCardinalities() { // SwitcherView should appear differently depending on number of views available // Multiple views -> Combo box // One view -> Label // No views -> Neither // Create the test object View switcherView = SwitcherView.VIEW_INFO.createView(mockComponent); // During normal initialization, should have two view infos. // A Combo Box should be found. Assert.assertNotNull(findComponent(switcherView, JComboBox.class)); // With only one view info, should have a label instead Mockito.when(mockComponent.getViewInfos(ViewType.OBJECT)) .thenReturn(Collections.singleton(mockViewInfo1)); switcherView = SwitcherView.VIEW_INFO.createView(mockComponent); Assert.assertNull(findComponent(switcherView, JComboBox.class)); Assert.assertNotNull(findComponent(switcherView, JLabel.class)); // With no views, there should be no label or combo box Mockito.when(mockComponent.getViewInfos(ViewType.OBJECT)) .thenReturn(Collections.<ViewInfo>emptySet()); switcherView = SwitcherView.VIEW_INFO.createView(mockComponent); Assert.assertNull(findComponent(switcherView, JComboBox.class)); Assert.assertNull(findComponent(switcherView, JLabel.class)); } @Test public void testBadInput() { // Make sure that view does not break for unexpected input // (verify that null checks are present.) // Create the test object View switcherView = SwitcherView.VIEW_INFO.createView(mockComponent); // Add monitored GUI can take a variety of object types // Make sure an unexpected object type does not trigger an exception switcherView.addMonitoredGUI(null); switcherView.addMonitoredGUI("hello"); Mockito.when(mockViewProvider.getHousedViewManifestation()) .thenReturn(null); switcherView.addMonitoredGUI(mockViewProvider); } @Test public void testAppearance() { // Exercise custom ComboBoxUI // Mostly visual, so not much to verify // Create the test object View switcherView = SwitcherView.VIEW_INFO.createView(mockComponent); // Find combo box so we can test its UI object @SuppressWarnings("rawtypes") JComboBox comboBox = findComponent(switcherView, JComboBox.class); ComboBoxUI ui = comboBox.getUI(); // Verify that ui paints a rounded rect (per spec) Graphics mockGraphics = Mockito.mock(Graphics.class, Mockito.RETURNS_MOCKS); ui.paint(mockGraphics, comboBox); Mockito.verify(mockGraphics).fillRoundRect( Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt(),Mockito.anyInt(),Mockito.anyInt(),Mockito.anyInt()); } @DataProvider public Object[][] generateSwitcherTests() { Object[][] tests = new Object[8][]; boolean[] truths = { true, false }; int i = 0; for (boolean addGUI : truths) { for (boolean doChange : truths) { for (boolean acceptChange : truths) { tests[i] = new Object[] { addGUI, doChange, acceptChange }; i++; } } } return tests; } private <T extends Container> T findComponent(Container c, Class<T> targetClass) { if (targetClass.isAssignableFrom(c.getClass())) { return targetClass.cast(c); } else { for (Component child : c.getComponents()) { if (child instanceof Container) { T comboBox = findComponent((Container) child, targetClass); if (comboBox != null) { return comboBox; } } } } return null; } }