org.assertj.swing.jide.grids.driver.AbstractComboBoxDriver Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of assertj-swing-jide Show documentation
Show all versions of assertj-swing-jide Show documentation
JIDE specific extensions for testing
/**
* 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.
*
* Copyright 2012-2015 the original author or authors.
*/
package org.assertj.swing.jide.grids.driver;
import static javax.swing.text.DefaultEditorKit.deletePrevCharAction;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.assertj.core.util.Preconditions.checkNotNull;
import static org.assertj.swing.edt.GuiActionRunner.execute;
import java.awt.Component;
import javax.swing.AbstractButton;
import javax.swing.ComboBoxEditor;
import javax.swing.JComponent;
import org.assertj.core.description.Description;
import org.assertj.core.util.Strings;
import org.assertj.swing.annotation.RunsInEDT;
import org.assertj.swing.core.KeyPressInfo;
import org.assertj.swing.driver.JComponentDriver;
import org.assertj.swing.exception.LocationUnavailableException;
import org.assertj.swing.query.ComponentEnabledQuery;
import com.jidesoft.combobox.AbstractComboBox;
import com.jidesoft.combobox.PopupPanel;
import com.jidesoft.converter.ConverterContext;
import com.jidesoft.converter.ObjectConverter;
/**
* A driver for an {@link com.jidesoft.combobox.AbstractComboBox}. This is loosely based
* on the {@link org.assertj.swing.driver.JComboBoxDriver} class so a familiar usage pattern
* will exist between Swing combo boxes and JIDE combo boxes.
*
* @author Peter Murray
*/
public class AbstractComboBoxDriver extends JComponentDriver {
private static final String EDITABLE_PROPERTY = "editable";
private static final String SELECTED_INDEX_PROPERTY = "selectedIndex";
protected AbstractComboBoxCellReader _cellReader;
public AbstractComboBoxDriver(org.assertj.swing.core.Robot robot) {
super(robot);
cellReader(new AbstractComboBoxCellReader());
}
/**
* Deletes the text of the {@code AbstractComboBox}.
*
* @param comboBox the target {@code AbstractComboBox}.
* @throws IllegalStateException if the {@code AbstractComboBox} is disabled.
* @throws IllegalStateException if the {@code AbstractComboBox} is not showing on the screen.
*/
@RunsInEDT
public void deleteText(AbstractComboBox comboBox) {
selectAllText(comboBox);
Component editor = accessibleEditorOf(comboBox);
if (!(editor instanceof JComponent)) {
return;
}
focus(editor);
invokeAction((JComponent) editor, deletePrevCharAction);
}
/**
* Simulates a user entering the specified text in the {@link com.jidesoft.combobox.AbstractComboBox}
,
* replacing any text. This action is executed only if the {@link
* com.jidesoft.combobox.AbstractComboBox}
is editable.
*
* @param comboBox the target AbstractComboBox
.
* @param text the text to enter.
* @throws IllegalStateException if the AbstractComboBox
is disabled.
* @throws IllegalStateException if the AbstractComboBox
is not showing on the
* screen.
* @throws IllegalStateException if the AbstractComboBox
is not editable.
*/
@RunsInEDT
public void replaceText(AbstractComboBox comboBox, String text) {
checkNotNull(text);
if (text.isEmpty()) {
deleteText(comboBox);
} else {
selectAllText(comboBox);
enterText(comboBox, text);
}
}
/**
* Simulates a user selecting the text in the {@link com.jidesoft.combobox.AbstractComboBox}
. This
* action is executed only if the {@link com.jidesoft.combobox.AbstractComboBox}
is editable.
*
* @param comboBox the target AbstractComboBox
.
* @throws IllegalStateException if the AbstractComboBox
is disabled.
* @throws IllegalStateException if the AbstractComboBox
is not showing on the
* screen.
* @throws IllegalStateException if the AbstractComboBox
is not editable.
*/
@RunsInEDT
public void selectAllText(AbstractComboBox comboBox) {
Component editor = accessibleEditorOf(comboBox);
if (!(editor instanceof JComponent)) {
return;
}
focus(editor);
invokeAction((JComponent) editor, javax.swing.text.DefaultEditorKit.selectAllAction);
}
@RunsInEDT
private static Component accessibleEditorOf(final AbstractComboBox comboBox) {
return org.assertj.swing.edt.GuiActionRunner.execute(() -> {
AbstractComboBoxAccessibleEditorValidator.validateEditorIsAccessible(comboBox);
return comboBox.getEditor().getEditorComponent();
});
}
/**
* We need to cater for the editor component if we are editable. When typing into an
* editable AbstractComboBox, the focus will move to the Editor, not the ComboBox
* instance which will result in AssertJ-Swing failing on waiting for focus to move to the
* comboBox.
*
* @param c the target component.
* @param keyCodes one or more codes of the keys to press.
*/
@Override
@RunsInEDT
public void pressAndReleaseKeys(Component c, int... keyCodes) {
Component interactionComponent = getInteractionComponent(c);
robot.moveMouse(interactionComponent);
robot.focus(interactionComponent);
super.pressAndReleaseKeys(interactionComponent, keyCodes);
}
/**
* We need to cater for the editor component if we are editable. When typing into an
* editable AbstractComboBox, the focus will move to the Editor, not the ComboBox
* instance which will result in AssertJ-Swing failing on waiting for focus to move to the
* comboBox.
*
* @param c the target component.
* @param keyPressInfo specifies the key and modifiers to press.
*/
@Override
@RunsInEDT
public void pressAndReleaseKey(Component c, KeyPressInfo keyPressInfo) {
Component interactionComponent = getInteractionComponent(c);
super.pressAndReleaseKey(interactionComponent,
keyPressInfo.keyCode(),
keyPressInfo.modifiers());
}
/**
* We need to cater for the editor component if we are editable. When typing into an
* editable AbstractComboBox, the focus will move to the Editor, not the ComboBox
* instance which will result in AssertJ-Swing failing on waiting for focus to move to the
* comboBox.
*
* @param c the target component.
* @param keyCode the code of the key to press.
* @param modifiers the given modifiers.
*/
@Override
@RunsInEDT
public void pressAndReleaseKey(Component c, int keyCode, int[] modifiers) {
Component interactionComponent = getInteractionComponent(c);
super.pressAndReleaseKey(interactionComponent, keyCode, modifiers);
}
@Override
@RunsInEDT
public void pressKey(Component c, int keyCode) {
Component interactionComponent = getInteractionComponent(c);
super.pressKey(interactionComponent, keyCode);
}
@Override
public void pressKeyWhileRunning(Component c, int keyCode, Runnable runnable) {
Component interactionComponent = getInteractionComponent(c);
super.pressKeyWhileRunning(interactionComponent, keyCode, runnable);
}
/**
* Simulates a user releasing the given key on the {@link Component}
.
*
* @param c the target component.
* @param keyCode the code of the key to release.
* @throws IllegalArgumentException if the given code is not a valid key code.
* @throws IllegalStateException if the Component
is disabled, or is not
* showing on the screen.
* @see java.awt.event.KeyEvent
*/
@Override
@RunsInEDT
public void releaseKey(Component c, int keyCode) {
Component interactionComponent = getInteractionComponent(c);
super.releaseKey(interactionComponent, keyCode);
}
public void requireSelection(AbstractComboBox comboBox, String value) {
String selectedItem = _cellReader.valueAsText(comboBox, comboBox.getSelectedItem());
if (selectedItem == null) {
fail(org.assertj.core.util.Strings.concat("[",
selectedIndexProperty(comboBox),
"] No selection"));
}
assertThat(selectedItem).as(selectedIndexProperty(comboBox)).isEqualTo(value);
}
/**
* Simulates a user entering the specified text in the {@link com.jidesoft.combobox.AbstractComboBox}
.
* This action is executed only if the {@link com.jidesoft.combobox.AbstractComboBox}
is editable.
*
* @param comboBox the target AbstractComboBox
.
* @param text the text to enter.
* @throws IllegalStateException if the AbstractComboBox
is disabled.
* @throws IllegalStateException if the AbstractComboBox
is not editable or
* is not showing on the screen.
*/
@RunsInEDT
public void enterText(AbstractComboBox comboBox, String text) {
inEdtValidateEditorIsAccessible(comboBox);
focus(comboBox);
robot.enterText(text);
}
@RunsInEDT
private static void inEdtValidateEditorIsAccessible(final AbstractComboBox comboBox) {
org.assertj.swing.edt.GuiActionRunner.execute(() -> AbstractComboBoxAccessibleEditorValidator.validateEditorIsAccessible(comboBox));
}
/**
* Asserts that the given {@link com.jidesoft.combobox.AbstractComboBox}
is editable.
*
* @param comboBox the target AbstractComboBox
.
* @throws AssertionError if the AbstractComboBox
is not editable.
*/
@RunsInEDT
public void requireEditable(final AbstractComboBox comboBox) {
assertEditable(comboBox, true);
}
/**
* Asserts that the given {@link com.jidesoft.combobox.AbstractComboBox}
is not editable.
*
* @param comboBox the given AbstractComboBox
.
* @throws AssertionError if the AbstractComboBox
is editable.
*/
@RunsInEDT
public void requireNotEditable(AbstractComboBox comboBox) {
assertEditable(comboBox, false);
}
@RunsInEDT
public void requireNotEnabled(AbstractComboBox comboBox) {
assertEnabled(comboBox, false);
}
@RunsInEDT
public void requireEnabled(AbstractComboBox comboBox) {
assertEnabled(comboBox, true);
}
@RunsInEDT
private void assertEditable(AbstractComboBox comboBox, boolean expected) {
assertThat(AbstractComboBoxEditableQuery.isEditable(comboBox))
.as(editableProperty(comboBox)).isEqualTo(expected);
}
@RunsInEDT
private void assertEnabled(AbstractComboBox comboBox, boolean expected) {
assertThat(ComponentEnabledQuery.isEnabled(comboBox))
.as(editableProperty(comboBox)).isEqualTo(expected);
}
@RunsInEDT
private static Description editableProperty(AbstractComboBox comboBox) {
return propertyName(comboBox, EDITABLE_PROPERTY);
}
public String getStringRepresentation(AbstractComboBox box, Object o) {
ObjectConverter converter = box.getConverter();
ConverterContext context = box.getConverterContext();
if (converter == null) {
return String.valueOf(o);
}
return converter.toString(o, context);
}
AbstractComboBox.EditorComponent getEditor(final AbstractComboBox comboBox) {
return execute(() -> (AbstractComboBox.EditorComponent) comboBox.getEditor());
}
public String getEditorText(final AbstractComboBox comboBox) {
return execute(() -> ((AbstractComboBox.EditorComponent) comboBox.getEditor()).getText());
}
public void requireEditorText(final AbstractComboBox comboBox, String requiredText) {
robot.waitForIdle();
String currentText = getEditorText(comboBox);
assertThat(currentText).as("Editor Text Value").isEqualTo(requiredText);
}
@RunsInEDT
PopupPanel showPopup(final AbstractComboBox comboBox) {
return comboBox.getPopupPanel();
}
public void requireNoSelection(AbstractComboBox comboBox) {
Object selectedItem = comboBox.getSelectedItem();
if (selectedItem != null) {
fail(Strings.concat("No selection is required, but selection value is, ",
selectedItem));
}
}
@RunsInEDT
void dropDownVisibleThroughComponent(AbstractComboBox comboBox, boolean visible) {
if (visible) {
if (!comboBox.isPopupVisible()) {
clickPopupButton(comboBox);
}
} else {
if (comboBox.isPopupVisible()) {
comboBox.hidePopup();
}
}
robot.waitForIdle();
}
int validateIndex(AbstractComboBox comboBox, int index) {
int itemCount = size(comboBox);
if (index >= 0 && index < itemCount) {
return index;
}
throw new LocationUnavailableException(Strings.concat("Item index (",
java.lang.String.valueOf(index),
") should be between [0] and [",
String.valueOf(itemCount - 1),
"] (inclusive)"));
}
/**
* Converts an object that may be present in the ComboBox into a String representation.
*
* @param comboBox The comboBox to convert the object for.
* @param o The object to convert into a String.
* @return The object passed in converted in to a String so that it would appear as it
* would to a user selecting the value in the ComboBox.
*/
protected String convertElementToString(AbstractComboBox comboBox, Object o) {
if (o == null) {
return null;
}
if (o instanceof String) {
return (String) o;
}
ObjectConverter converter = comboBox.getConverter();
if (converter != null) {
return converter.toString(o, comboBox.getConverterContext());
}
return o.toString();
}
protected boolean isDropDownVisible(AbstractComboBox comboBox) {
return comboBox.isPopupVisible();
}
protected int size(AbstractComboBox comboBox) {
return comboBox.getModel().getSize();
}
protected Object itemAt(AbstractComboBox comboBox, int index) {
return comboBox.getModel().getElementAt(index);
}
protected boolean areEqual(AbstractComboBox combo, Object o1, Object o2) {
String s1 = getStringRepresentation(combo, o1);
String s2 = getStringRepresentation(combo, o2);
return s1.equals(s2);
}
protected String selectedIndexProperty(AbstractComboBox comboBox) {
return propertyName(comboBox, SELECTED_INDEX_PROPERTY).toString();
}
/**
* Updates the implementation of {@link AbstractComboBoxCellReader}
to use
* when comparing internal values of a {@link com.jidesoft.combobox.ListComboBox}
and the values expected
* in a test.
*
* @param newCellReader the new ListComboBoxCellValueReader
to use.
* @throws IllegalArgumentException if newCellReader
is null
.
*/
public void cellReader(AbstractComboBoxCellReader newCellReader) {
// TODO move this back to CommonConditions.validateCellReader()
// validateCellReader(newCellReader);
if (newCellReader == null) {
throw new NullPointerException("Cell reader should not be null");
}
_cellReader = newCellReader;
}
@RunsInEDT
public void clickPopupButton(final AbstractComboBox comboBox) {
AbstractButton button = comboBox.getPopupButton();
robot.moveMouse(button);
robot.click(button);
robot.waitForIdle();
}
/**
* Obtains the component that the user will interact with, which could be the actual
* combo box, or the editor component, depending upon the state of the combo box.
*
* @param c The Component to obtain the interactive component from.
* @return The {@link java.awt.Component} that the user is to interact with.
*/
@RunsInEDT
protected Component getInteractionComponent(Component c) {
if (c instanceof AbstractComboBox) {
AbstractComboBox combo = (AbstractComboBox) c;
if (combo.isEditable()) {
ComboBoxEditor editor = combo.getEditor();
return editor.getEditorComponent();
}
}
return c;
}
@RunsInEDT
public void requirePopupVisible(final AbstractComboBox target, boolean visible) {
Boolean isVisible = execute(() -> target.isPopupVisible());
assertThat(isVisible).as("Popup Visibility").isEqualTo(visible);
}
}