/* * Created on Jul 12, 2007 * * 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 @2007-2009 the original author or authors. */ package org.fest.swing.fixture; import java.awt.Color; import java.awt.Font; import java.awt.Point; import javax.swing.JTable; import javax.swing.table.JTableHeader; import org.fest.assertions.Description; import org.fest.swing.cell.JTableCellReader; import org.fest.swing.cell.JTableCellWriter; import org.fest.swing.core.KeyPressInfo; import org.fest.swing.core.MouseButton; import org.fest.swing.core.MouseClickInfo; import org.fest.swing.core.Robot; import org.fest.swing.data.TableCell; import org.fest.swing.data.TableCellByColumnId; import org.fest.swing.driver.BasicJTableCellReader; import org.fest.swing.driver.BasicJTableCellWriter; import org.fest.swing.driver.JTableDriver; import org.fest.swing.exception.ActionFailedException; import org.fest.swing.exception.ComponentLookupException; import org.fest.swing.exception.WaitTimedOutError; import org.fest.swing.timing.Timeout; import static org.fest.assertions.Assertions.assertThat; import static org.fest.swing.driver.ComponentDriver.propertyName; import static org.fest.util.Strings.concat; /** * Understands simulation of user events on a {@link JTable} and verification of the state of such * {@link JTable}. *

* The conversion between the values given in tests and the values being displayed by a {@link JTable} * renderer is performed by a {@link JTableCellReader}. This fixture uses a * {@link BasicJTableCellReader} by default. *

* * @author Alex Ruiz * @author Yvonne Wang * @author Fabien Barbero */ public class JTableFixture extends JPopupMenuInvokerFixture implements CommonComponentFixture { private JTableDriver driver; /** * Creates a new {@link JTableFixture}. * @param robot performs simulation of user events on the given JTable. * @param target the JTable to be managed by this fixture. * @throws NullPointerException if robot is null. * @throws NullPointerException if target is null. */ public JTableFixture(Robot robot, JTable target) { super(robot, target); updateDriver(createDefaultDriver()); } /** * Creates a new {@link JTableFixture}. * @param robot performs simulation of user events on a JTable. * @param tableName the name of the JTable to find using the given Robot. * @throws NullPointerException if robot is null. * @throws ComponentLookupException if a matching JTable could not be found. * @throws ComponentLookupException if more than one matching JTable is found. */ public JTableFixture(Robot robot, String tableName) { super(robot, tableName, JTable.class); updateDriver(createDefaultDriver()); } protected JTableDriver createDefaultDriver() { return new JTableDriver(robot); } final void updateDriver(JTableDriver newDriver) { driver = newDriver; } /** * Returns the {@link JTableDriver} used by this fixture. * @return the JTableDriver used by this fixture. */ protected final JTableDriver driver() { return driver; } /** * Returns a fixture that verifies the font of the given table cell. * @param cell the given table cell. * @return a fixture that verifies the font of the given table cell. * @throws NullPointerException if the cell is null. * @throws IndexOutOfBoundsException if any of the indices (row and column) is out of bounds. */ public FontFixture fontAt(TableCell cell) { Font font = driver.font(target, cell); return new FontFixture(font, cellProperty(cell, FONT_PROPERTY)); } /** * Returns a fixture that verifies the background color of the given table cell. * @param cell the given table cell. * @return a fixture that verifies the background color of the given table cell. * @throws NullPointerException if the cell is null. * @throws IndexOutOfBoundsException if any of the indices (row and column) is out of bounds. */ public ColorFixture backgroundAt(TableCell cell) { Color background = driver.background(target, cell); return new ColorFixture(background, cellProperty(cell, BACKGROUND_PROPERTY)); } /** * Returns a fixture that verifies the foreground color of the given table cell. * @param cell the given table cell. * @return a fixture that verifies the foreground color of the given table cell. * @throws NullPointerException if the cell is null. * @throws IndexOutOfBoundsException if any of the indices (row and column) is out of bounds. */ public ColorFixture foregroundAt(TableCell cell) { Color foreground = driver.foreground(target, cell); return new ColorFixture(foreground, cellProperty(cell, FOREGROUND_PROPERTY)); } private Description cellProperty(TableCell cell, String propertyName) { return propertyName(target, concat(propertyName, " ", cell)); } /** * Returns a fixture that manages the table cell whose value matches the given one. * @param value the value of the cell to look for. * @return a fixture that manages the table cell whose value matches the given one. * @throws ActionFailedException if a cell with a matching value cannot be found. */ public TableCell cell(String value) { return driver.cell(target, value); } /** * Returns a fixture that manages the table cell specified by the given row index and column name. * @param cell the cell of interest. * @return a fixture that manages the table cell specified by the given row index and column name. * @throws NullPointerException if the cell is null. * @throws IndexOutOfBoundsException if the row index in the given cell is out of bounds. * @throws ActionFailedException if a column with a matching name could not be found. */ public JTableCellFixture cell(TableCellByColumnId cell) { return new JTableCellFixture(this, driver.cell(target, cell)); } /** * Returns a fixture that manages the table cell specified by the given row and column. * @param cell the cell of interest. * @return a fixture that manages the table cell specified by the given row and column. * @throws NullPointerException if the cell is null. * @throws IndexOutOfBoundsException if any of the indices (row and column) is out of bounds. */ public JTableCellFixture cell(TableCell cell) { driver.validate(target, cell); return new JTableCellFixture(this, cell); } /** * Returns a {@link JTableHeaderFixture} wrapping the {@link JTableHeader} in this fixture's * {@link JTable}. * @return a JTableHeaderFixture wrapping the JTableHeader in this fixture's * JTable. * @throws AssertionError if the JTableHeader in this fixture's JTable is null. */ public JTableHeaderFixture tableHeader() { JTableHeader tableHeader = driver.tableHeaderOf(target); assertThat(tableHeader).isNotNull(); return new JTableHeaderFixture(robot, tableHeader); } /** * Returns the String representation of the selected cell in this fixture's {@link JTable}, * using this fixture's {@link JTableCellReader}. Returns null if one can not be obtained or * if the {@link JTable} does not have any selected cell. * @return the String representation of the selected cell. * @see #cellReader(JTableCellReader) */ public String selectionValue() { return driver.selectionValue(target); } /** * Converts the given cell into a coordinate pair. * @param cell the given cell. * @return the coordinates of the given cell. * @throws NullPointerException if the cell is null. * @throws IndexOutOfBoundsException if any of the indices (row and column) is out of bounds. */ public Point pointAt(TableCell cell) { return driver.pointAt(target, cell); } /** * Returns the String representation of the cells in the in this fixture's {@link JTable}, * using this fixture's {@link JTableCellReader}. * @return the String representation of the cells in thi fixture's JTable. * @see #cellReader(JTableCellReader) */ public String[][] contents() { return driver.contents(target); } /** * Returns the number of rows that can be shown in this fixture's {@link JTable}, given unlimited space. * @return the number of rows shown in this fixture's JTable. * @see JTable#getRowCount() */ public int rowCount() { return driver.rowCountOf(target); } /** * Returns the String representation of the value of a cell in this fixture's * {@link JTable}, using this fixture's {@link JTableCellReader}. * @param cell the given cell. * @return the String representation of the value of a cell in this fixture's JTable. * @throws NullPointerException if the cell is null. * @throws IndexOutOfBoundsException if any of the indices (row and column) is out of bounds. * @see #cellReader(JTableCellReader) */ public String valueAt(TableCell cell) { return driver.value(target, cell); } /** * Simulates a user selecting the given cell (row and column) of this fixture's {@link JTable}. * @param cell the cell to select. * @return this fixture. * @throws NullPointerException if the cell is null. * @throws IllegalStateException if this fixture's JTable is disabled. * @throws IllegalStateException if this fixture's JTable is not showing on the screen. * @throws IndexOutOfBoundsException if any of the indices (row and column) is out of bounds. */ public JTableFixture selectCell(TableCell cell) { driver.selectCell(target, cell); return this; } /** * Simulates a user selecting the given cells of this fixture's {@link JTable}. * @param cells the cells to select. * @return this fixture. * @throws NullPointerException if cells is null or empty. * @throws IllegalArgumentException if cells is null or empty. * @throws IllegalStateException if this fixture's JTable is disabled. * @throws IllegalStateException if this fixture's JTable is not showing on the screen. * @throws NullPointerException if any element in cells is null. * @throws IndexOutOfBoundsException if any of the indices of any of the cells are out of bounds. */ public JTableFixture selectCells(TableCell... cells) { driver.selectCells(target, cells); return this; } /** * Simulates a user dragging an item from this fixture's {@link JTable}. * @param cell the cell to drag. * @return this fixture. * @throws NullPointerException if the cell is null. * @throws IllegalStateException if this fixture's JTable is disabled. * @throws IllegalStateException if this fixture's JTable is not showing on the screen. * @throws IndexOutOfBoundsException if any of the indices (row and column) is out of bounds. */ public JTableFixture drag(TableCell cell) { driver.drag(target, cell); return this; } /** * Simulates a user dropping an item to this fixture's {@link JTable}. * @param cell the cell to drop the dragging item into. * @return this fixture. * @throws NullPointerException if the cell is null. * @throws IllegalStateException if this fixture's JTable is disabled. * @throws IllegalStateException if this fixture's JTable is not showing on the screen. * @throws IndexOutOfBoundsException if any of the indices (row and column) is out of bounds. */ public JTableFixture drop(TableCell cell) { driver.drop(target, cell); return this; } /** * Simulates a user clicking this fixture's {@link JTable}. * @return this fixture. * @throws IllegalStateException if this fixture's JTable is disabled. * @throws IllegalStateException if this fixture's JTable is not showing on the screen. */ public JTableFixture click() { driver.click(target); return this; } /** * Simulates a user clicking this fixture's {@link JTable}. * @param button the button to click. * @return this fixture. * @throws NullPointerException if the given MouseButton is null. * @throws IllegalStateException if this fixture's JTable is disabled. * @throws IllegalStateException if this fixture's JTable is not showing on the screen. */ public JTableFixture click(MouseButton button) { driver.click(target, button); return this; } /** * Simulates a user clicking this fixture's {@link JTable}. * @param mouseClickInfo specifies the button to click and the times the button should be clicked. * @return this fixture. * @throws NullPointerException if the given MouseClickInfo is null. * @throws IllegalStateException if this fixture's JTable is disabled. * @throws IllegalStateException if this fixture's JTable is not showing on the screen. */ public JTableFixture click(MouseClickInfo mouseClickInfo) { driver.click(target, mouseClickInfo); return this; } /** * Simulates a user clicking a cell in this fixture's {@link JTable} once, using the specified mouse * button. * @param cell the cell to click. * @param button the mouse button to use. * @return this fixture. * @throws NullPointerException if the cell is null. * @throws IllegalStateException if this fixture's JTable is disabled. * @throws IllegalStateException if this fixture's JTable is not showing on the screen. * @throws IndexOutOfBoundsException if any of the indices (row and column) is out of bounds. */ public JTableFixture click(TableCell cell, MouseButton button) { click(cell, button, 1); return this; } /** * Simulates a user clicking a cell in this fixture's {@link JTable}, using the specified mouse button * the given number of times. * @param cell the cell to click. * @param mouseClickInfo specifies the mouse button to use and how many times to click. * @return this fixture. * @throws NullPointerException if the given MouseClickInfo is null. * @throws NullPointerException if the cell is null. * @throws IllegalStateException if this fixture's JTable is disabled. * @throws IllegalStateException if this fixture's JTable is not showing on the screen. * @throws IndexOutOfBoundsException if any of the indices (row and column) is out of bounds. */ public JTableFixture click(TableCell cell, MouseClickInfo mouseClickInfo) { if (mouseClickInfo == null) throw new NullPointerException("The given MouseClickInfo should not be null"); click(cell, mouseClickInfo.button(), mouseClickInfo.times()); return this; } void click(TableCell cell, MouseButton button, int times) { driver.click(target, cell, button, times); } /** * Simulates a user double-clicking this fixture's {@link JTable}. *

* Note: This method will not be successful if the double-clicking occurs on an editable table cell. For this * particular case, this method will start edition of the table cell located under the mouse pointer. *

* @return this fixture. * @throws IllegalStateException if this fixture's JTable is disabled. * @throws IllegalStateException if this fixture's JTable is not showing on the screen. */ public JTableFixture doubleClick() { driver.doubleClick(target); return this; } /** * Simulates a user right-clicking this fixture's {@link JTable}. * @return this fixture. * @throws IllegalStateException if this fixture's JTable is disabled. * @throws IllegalStateException if this fixture's JTable is not showing on the screen. */ public JTableFixture rightClick() { driver.rightClick(target); return this; } /** * Simulates a user pressing given key with the given modifiers on this fixture's {@link JTable}. * Modifiers is a mask from the available {@link java.awt.event.InputEvent} masks. * @param keyPressInfo specifies the key and modifiers to press. * @return this fixture. * @throws NullPointerException if the given KeyPressInfo is null. * @throws IllegalArgumentException if the given code is not a valid key code. * @throws IllegalStateException if this fixture's JTable is disabled. * @throws IllegalStateException if this fixture's JTable is not showing on the screen. * @see KeyPressInfo */ public JTableFixture pressAndReleaseKey(KeyPressInfo keyPressInfo) { driver.pressAndReleaseKey(target, keyPressInfo); return this; } /** * Simulates a user pressing and releasing the given keys on this fixture's {@link JTable}. This method * does not affect the current focus. * @param keyCodes one or more codes of the keys to press. * @return this fixture. * @throws NullPointerException if the given array of codes is null. * @throws IllegalArgumentException if any of the given code is not a valid key code. * @throws IllegalStateException if this fixture's JTable is disabled. * @throws IllegalStateException if this fixture's JTable is not showing on the screen. * @see java.awt.event.KeyEvent */ public JTableFixture pressAndReleaseKeys(int... keyCodes) { driver.pressAndReleaseKeys(target, keyCodes); return this; } /** * Simulates a user pressing the given key on this fixture's {@link JTable}. * @param keyCode the code of the key to press. * @return this fixture. * @throws IllegalArgumentException if any of the given code is not a valid key code. * @throws IllegalStateException if this fixture's JTable is disabled. * @throws IllegalStateException if this fixture's JTable is not showing on the screen. * @see java.awt.event.KeyEvent */ public JTableFixture pressKey(int keyCode) { driver.pressKey(target, keyCode); return this; } /** * Simulates a user releasing the given key on this fixture's {@link JTable}. * @param keyCode the code of the key to release. * @return this fixture. * @throws IllegalArgumentException if any of the given code is not a valid key code. * @throws IllegalStateException if this fixture's JTable is disabled. * @throws IllegalStateException if this fixture's JTable is not showing on the screen. * @see java.awt.event.KeyEvent */ public JTableFixture releaseKey(int keyCode) { driver.releaseKey(target, keyCode); return this; } /** * Gives input focus to this fixture's {@link JTable}. * @throws IllegalStateException if this fixture's JTable is disabled. * @throws IllegalStateException if this fixture's JTable is not showing on the screen. * @return this fixture. */ public JTableFixture focus() { driver.focus(target); return this; } /** * Shows a pop-up menu at the given cell. * @param cell the table cell where to show the pop-up menu. * @return a fixture that manages the displayed pop-up menu. * @throws NullPointerException if the cell is null. * @throws IllegalStateException if this fixture's JTable is disabled. * @throws IllegalStateException if this fixture's JTable is not showing on the screen. * @throws ComponentLookupException if a pop-up menu cannot be found. */ public JPopupMenuFixture showPopupMenuAt(TableCell cell) { return new JPopupMenuFixture(robot, driver.showPopupMenuAt(target, cell)); } /** * Enters the given value in the given cell of this fixture's {@link JTable}, using this fixture's * {@link JTableCellWriter}. If you need more flexibility for editing cell, please see * {@link JTableCellFixture#editor()}. * @param cell the given cell. * @param value the given value. * @return this fixture. * @throws NullPointerException if the cell is null. * @throws IllegalStateException if this fixture's JTable is disabled. * @throws IllegalStateException if this fixture's JTable is not showing on the screen. * @throws IllegalStateException if this fixture's JTable is not editable. * @throws IndexOutOfBoundsException if any of the indices (row and column) is out of bounds. * @throws ActionFailedException if this fixture's JTableCellValueReader is unable to enter the given * value. * @see #cellWriter(JTableCellWriter) * @see JTableCellFixture#editor() */ public JTableFixture enterValue(TableCell cell, String value) { driver.enterValueInCell(target, cell, value); return this; } /** * Updates the implementation of {@link JTableCellReader} to use when comparing internal values of this * fixture's {@link JTable} and the values expected in a test. The default implementation to use is * {@link BasicJTableCellReader}. * @param cellReader the new JTableCellValueReader to use. * @throws NullPointerException if cellReader is null. * @return this fixture. */ public JTableFixture cellReader(JTableCellReader cellReader) { driver.cellReader(cellReader); return this; } /** * Asserts that this fixture's {@link JTable} has the given number of rows. * @param expected the expected number of rows. * @return this fixture. * @throws AssertionError if this fixture's JTable does not have the given number of rows. */ public JTableFixture requireRowCount(int expected) { driver.requireRowCount(target, expected); return this; } /** * Asserts that this fixture's {@link JTable} has the given number of columns. * @param expected the expected number of columns. * @return this fixture. * @throws AssertionError if this fixture's JTable does not have the given number of columns. */ public JTableFixture requireColumnCount(int expected) { driver.requireColumnCount(target, expected); return this; } /** * Asserts that this fixture's {@link JTable} has input focus. * @return this fixture. * @throws AssertionError if this fixture's JTable does not have input focus. */ public JTableFixture requireFocused() { driver.requireFocused(target); return this; } /** * Asserts that this fixture's {@link JTable} is enabled. * @return this fixture. * @throws AssertionError is the managed JTable is disabled. */ public JTableFixture requireEnabled() { driver.requireEnabled(target); return this; } /** * Asserts that this fixture's {@link JTable} is enabled. * @param timeout the time this fixture will wait for the component to be enabled. * @return this fixture. * @throws WaitTimedOutError if the managed JTable is never enabled. */ public JTableFixture requireEnabled(Timeout timeout) { driver.requireEnabled(target, timeout); return this; } /** * Asserts that this fixture's {@link JTable} is disabled. * @return this fixture. * @throws AssertionError is the managed JTable is enabled. */ public JTableFixture requireDisabled() { driver.requireDisabled(target); return this; } /** * Asserts that this fixture's {@link JTable} is visible. * @return this fixture. * @throws AssertionError if the managed JTable is not visible. */ public JTableFixture requireVisible() { driver.requireVisible(target); return this; } /** * Asserts that this fixture's {@link JTable} is not visible. * @return this fixture. * @throws AssertionError if the managed JTable is visible. */ public JTableFixture requireNotVisible() { driver.requireNotVisible(target); return this; } /** * Asserts that the given cell in this fixture's {@link JTable} is editable. * @param cell the given cell. * @return this fixture. * @throws NullPointerException if the cell is null. * @throws IndexOutOfBoundsException if any of the indices (row and column) is out of bounds. * @throws AssertionError if the given cell is not editable. */ public JTableFixture requireEditable(TableCell cell) { driver.requireEditable(target, cell); return this; } /** * Asserts that the given cell in this fixture's {@link JTable} is not editable. * @param cell the given cell. * @return this fixture. * @throws NullPointerException if the cell is null. * @throws IndexOutOfBoundsException if any of the indices (row and column) is out of bounds. * @throws AssertionError if the given cell is editable. */ public JTableFixture requireNotEditable(TableCell cell) { driver.requireNotEditable(target, cell); return this; } /** * Verifies that this fixture's {@link JTable} does not have any selection. * @return this fixture. * @throws AssertionError if this fixture's JTable has a selection. */ public JTableFixture requireNoSelection() { driver.requireNoSelection(target); return this; } /** * Asserts that the value of the given cell is equal to the expected one. * @param cell the given table cell. * @param value the expected value. * @return this fixture. * @throws NullPointerException if the cell is null. * @throws IndexOutOfBoundsException if any of the indices (row and column) is out of bounds. * @throws AssertionError if the value of the given cell is not equal to the expected one. */ public JTableFixture requireCellValue(TableCell cell, String value) { driver.requireCellValue(target, cell, value); return this; } /** * Asserts that the String representation of the cell values in this fixture's * {@link JTable} is equal to the given String array. This method uses this fixture's * {@link JTableCellReader} to read the values of the table cells as Strings. * @param contents the expected String representation of the cell values in this fixture's * JTable. * @see #cellReader(JTableCellReader) */ public void requireContents(String[][] contents) { driver.requireContents(target, contents); } /** * Updates the implementation of {@link JTableCellWriter} to use when comparing internal values of this * fixture's {@link JTable} and the values expected in a test. The default implementation to use is * {@link BasicJTableCellWriter}. * @param cellWriter the new JTableCellValueWriter to use. * @throws NullPointerException if cellWriter is null. * @return this fixture. */ public JTableFixture cellWriter(JTableCellWriter cellWriter) { driver.cellWriter(cellWriter); return this; } /** * Returns the index of the column in this fixture's {@link JTable} whose name matches the given one. * @param columnName the name of the column to look for. * @return the index of the column whose name matches the given one. * @throws ActionFailedException if a column with a matching name could not be found. */ public int columnIndexFor(Object columnName) { return driver.columnIndex(target, columnName); } }