diff options
Diffstat (limited to 'uitest/src/com/vaadin/tests/components/AbstractComponentTest.java')
-rw-r--r-- | uitest/src/com/vaadin/tests/components/AbstractComponentTest.java | 744 |
1 files changed, 744 insertions, 0 deletions
diff --git a/uitest/src/com/vaadin/tests/components/AbstractComponentTest.java b/uitest/src/com/vaadin/tests/components/AbstractComponentTest.java new file mode 100644 index 0000000000..ece40f5b00 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/AbstractComponentTest.java @@ -0,0 +1,744 @@ +package com.vaadin.tests.components; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import com.vaadin.event.FieldEvents.BlurEvent; +import com.vaadin.event.FieldEvents.BlurListener; +import com.vaadin.event.FieldEvents.BlurNotifier; +import com.vaadin.event.FieldEvents.FocusEvent; +import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.event.FieldEvents.FocusNotifier; +import com.vaadin.server.Resource; +import com.vaadin.server.ThemeResource; +import com.vaadin.tests.util.Log; +import com.vaadin.tests.util.LoremIpsum; +import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.MenuBar; +import com.vaadin.ui.MenuBar.MenuItem; +import com.vaadin.ui.themes.BaseTheme; + +public abstract class AbstractComponentTest<T extends AbstractComponent> + extends AbstractComponentTestCase<T> implements FocusListener, + BlurListener { + + protected static final String TEXT_SHORT = "Short"; + protected static final String TEXT_MEDIUM = "This is a semi-long text that might wrap."; + protected static final String TEXT_LONG = "This is a long text. " + + LoremIpsum.get(500); + protected static final String TEXT_VERY_LONG = "This is a very, very long text. " + + LoremIpsum.get(5000); + + private static final Resource SELECTED_ICON = new ThemeResource( + "../runo/icons/16/ok.png"); + + private static final LinkedHashMap<String, String> sizeOptions = new LinkedHashMap<String, String>(); + static { + sizeOptions.put("auto", null); + sizeOptions.put("50%", "50%"); + sizeOptions.put("100%", "100%"); + for (int w = 200; w < 1000; w += 100) { + sizeOptions.put(w + "px", w + "px"); + } + } + + // Menu related + + private MenuItem mainMenu; + + private MenuBar menu; + + private MenuItem settingsMenu; + + private T component; + + // Used to determine if a menuItem should be selected and the other + // unselected on click + private Set<MenuItem> parentOfSelectableMenuItem = new HashSet<MenuItem>(); + + /** + * Maps the category name to a menu item + */ + private Map<String, MenuItem> categoryToMenuItem = new HashMap<String, MenuItem>(); + private Map<MenuItem, String> menuItemToCategory = new HashMap<MenuItem, String>(); + + // Logging + private Log log; + + protected static final String CATEGORY_STATE = "State"; + protected static final String CATEGORY_SIZE = "Size"; + protected static final String CATEGORY_SELECTION = "Selection"; + protected static final String CATEGORY_LISTENERS = "Listeners"; + protected static final String CATEGORY_FEATURES = "Features"; + protected static final String CATEGORY_ACTIONS = "Actions"; + protected static final String CATEGORY_DECORATIONS = "Decorations"; + + @Override + protected final void setup() { + setTheme("tests-components"); + + // Create menu here so it appears before the components + addComponent(createMainMenu()); + + getLayout().setSizeFull(); + createLog(); + super.setup(); + + // Create menu actions and trigger default actions + createActions(); + + // Clear initialization log messages + log.clear(); + } + + private MenuBar createMainMenu() { + menu = new MenuBar(); + menu.setId("menu"); + mainMenu = menu.addItem("Component", null); + settingsMenu = menu.addItem("Settings", null); + populateSettingsMenu(settingsMenu); + + return menu; + } + + /** + * Override to add items to the "settings" menu. + * + * NOTE, Call super class first to preserve current order. If you override + * this in a class and another class overrides it you might break tests + * because the wrong items will be selected. + * + * @param settingsMenu + */ + protected void populateSettingsMenu(MenuItem settingsMenu) { + + MenuItem showEventLog = settingsMenu.addItem("Show event log", + new MenuBar.Command() { + + @Override + public void menuSelected(MenuItem selectedItem) { + boolean selected = !isSelected(selectedItem); + setLogVisible(selected); + setSelected(selectedItem, selected); + } + + }); + setSelected(showEventLog, true); + + settingsMenu.addItem("Clear log", new MenuBar.Command() { + + @Override + public void menuSelected(MenuItem selectedItem) { + log.clear(); + } + }); + MenuItem layoutSize = settingsMenu.addItem("Parent layout size", null); + MenuItem layoutWidth = layoutSize.addItem("Width", null); + MenuItem layoutHeight = layoutSize.addItem("Height", null); + for (final String name : sizeOptions.keySet()) { + layoutWidth.addItem(name, new MenuBar.Command() { + @Override + public void menuSelected(MenuItem selectedItem) { + getTestComponents().get(0).getParent() + .setWidth(sizeOptions.get(name)); + log("Parent layout width set to " + name); + } + }); + layoutHeight.addItem(name, new MenuBar.Command() { + @Override + public void menuSelected(MenuItem selectedItem) { + getTestComponents().get(0).getParent() + .setHeight(sizeOptions.get(name)); + log("Parent layout height set to " + name); + } + }); + } + + } + + protected void setLogVisible(boolean visible) { + // This is only to be screenshot-compatible with Vaadin 6, where + // invisible components cause spacing + if (visible) { + log.setHeight(null); + log.setWidth(null); + log.setCaption((String) log.getData()); + } else { + log.setHeight("0px"); + log.setWidth("0px"); + log.setCaption(null); + } + } + + private void createLog() { + log = new Log(5).setNumberLogRows(true); + log.setData(log.getCaption()); + log.setStyleName(BaseTheme.CLIP); + getLayout().addComponent(log, 1); + } + + /** + * By default initializes just one instance of {@link #getTestClass()} using + * {@link #constructComponent()}. + */ + @Override + protected void initializeComponents() { + component = constructComponent(); + component.setId("testComponent"); + addTestComponent(component); + } + + public T getComponent() { + return component; + } + + @Override + protected void addTestComponent(T c) { + super.addTestComponent(c); + getLayout().setExpandRatio(c, 1); + + }; + + /** + * Construct the component that is to be tested. This method uses a no-arg + * constructor by default. Override to customize. + * + * @return Instance of the component that is to be tested. + * @throws IllegalAccessException + * @throws InstantiationException + */ + protected T constructComponent() { + try { + return getTestClass().newInstance(); + } catch (Exception e) { + throw new RuntimeException("Failed to instantiate " + + getTestClass(), e); + } + } + + /** + * Create actions for the component. Remember to call super.createActions() + * when overriding. + */ + protected void createActions() { + createBooleanAction("Immediate", CATEGORY_STATE, true, immediateCommand); + createBooleanAction("Enabled", CATEGORY_STATE, true, enabledCommand); + createBooleanAction("Readonly", CATEGORY_STATE, false, readonlyCommand); + createBooleanAction("Visible", CATEGORY_STATE, true, visibleCommand); + createBooleanAction("Error indicator", CATEGORY_STATE, false, + errorIndicatorCommand); + createLocaleSelect(CATEGORY_STATE); + createErrorMessageSelect(CATEGORY_DECORATIONS); + + createDescriptionSelect(CATEGORY_DECORATIONS); + createCaptionSelect(CATEGORY_DECORATIONS); + createIconSelect(CATEGORY_DECORATIONS); + + createWidthAndHeightActions(CATEGORY_SIZE); + + createStyleNameSelect(CATEGORY_DECORATIONS); + + } + + protected Command<T, Boolean> focusListenerCommand = new Command<T, Boolean>() { + + @Override + public void execute(T c, Boolean value, Object data) { + if (value) { + ((FocusNotifier) c).addListener(AbstractComponentTest.this); + } else { + ((FocusNotifier) c).removeListener(AbstractComponentTest.this); + } + } + }; + protected Command<T, Boolean> blurListenerCommand = new Command<T, Boolean>() { + + @Override + public void execute(T c, Boolean value, Object data) { + if (value) { + ((BlurNotifier) c).addListener(AbstractComponentTest.this); + } else { + ((BlurNotifier) c).removeListener(AbstractComponentTest.this); + } + } + }; + + protected void createFocusListener(String category) { + createBooleanAction("Focus listener", category, false, + focusListenerCommand); + + } + + protected void createBlurListener(String category) { + createBooleanAction("Blur listener", category, false, + blurListenerCommand); + + } + + private void createStyleNameSelect(String category) { + LinkedHashMap<String, String> options = new LinkedHashMap<String, String>(); + options.put("-", null); + options.put("Light blue background (background-lightblue)", + "background-lightblue"); + options.put("1px red border (border-red-1px)", "border-red-1px"); + options.put("2px blue border (border-blue-2px)", "border-blue-2px"); + createComponentStyleNames(options); + createSelectAction("Style name", category, options, "-", + styleNameCommand); + + } + + protected void createComponentStyleNames( + LinkedHashMap<String, String> options) { + + } + + private void createErrorMessageSelect(String category) { + LinkedHashMap<String, String> options = new LinkedHashMap<String, String>(); + options.put("-", null); + options.put(TEXT_SHORT, TEXT_SHORT); + options.put("Medium", TEXT_MEDIUM); + options.put("Long", TEXT_LONG); + options.put("Very long", TEXT_VERY_LONG); + createSelectAction("Error message", category, options, "-", + errorMessageCommand); + + } + + private void createDescriptionSelect(String category) { + LinkedHashMap<String, String> options = new LinkedHashMap<String, String>(); + options.put("-", null); + options.put(TEXT_SHORT, TEXT_SHORT); + options.put("Medium", TEXT_MEDIUM); + options.put("Long", TEXT_LONG); + options.put("Very long", TEXT_VERY_LONG); + createSelectAction("Description / tooltip", category, options, "-", + descriptionCommand); + + } + + private void createCaptionSelect(String category) { + createSelectAction("Caption", category, createCaptionOptions(), + "Short", captionCommand); + + } + + protected LinkedHashMap<String, String> createCaptionOptions() { + LinkedHashMap<String, String> options = new LinkedHashMap<String, String>(); + options.put("-", null); + options.put("Short", TEXT_SHORT); + options.put("Medium", TEXT_MEDIUM); + options.put("Long", TEXT_LONG); + options.put("Very long", TEXT_VERY_LONG); + return options; + } + + private void createWidthAndHeightActions(String category) { + String widthCategory = "Width"; + String heightCategory = "Height"; + + createCategory(widthCategory, category); + createCategory(heightCategory, category); + + for (String name : sizeOptions.keySet()) { + createClickAction(name, widthCategory, widthCommand, + sizeOptions.get(name)); + createClickAction(name, heightCategory, heightCommand, + sizeOptions.get(name)); + } + + // Default to undefined size + for (T c : getTestComponents()) { + c.setWidth(null); + c.setHeight(null); + } + } + + private void createIconSelect(String category) { + LinkedHashMap<String, Resource> options = new LinkedHashMap<String, Resource>(); + options.put("-", null); + options.put("16x16", ICON_16_USER_PNG_CACHEABLE); + options.put("32x32", ICON_32_ATTENTION_PNG_CACHEABLE); + options.put("64x64", ICON_64_EMAIL_REPLY_PNG_CACHEABLE); + + createSelectAction("Icon", category, options, "-", iconCommand, null); + } + + private void createLocaleSelect(String category) { + LinkedHashMap<String, Locale> options = new LinkedHashMap<String, Locale>(); + options.put("-", null); + options.put("fi_FI", new Locale("fi", "FI")); + options.put("en_US", Locale.US); + options.put("zh_CN", Locale.SIMPLIFIED_CHINESE); + options.put("fr_FR", Locale.FRANCE); + + createSelectAction("Locale", category, options, "en_US", localeCommand, + null); + } + + protected void createBooleanAction(String caption, String category, + boolean initialState, final Command<T, Boolean> command) { + createBooleanAction(caption, category, initialState, command, null); + } + + protected <DATATYPE> void createBooleanAction(String caption, + String category, boolean initialState, + final Command<T, Boolean> command, Object data) { + MenuItem categoryItem = getCategoryMenuItem(category); + MenuItem item = categoryItem.addItem(caption, + menuBooleanCommand(command, data)); + setSelected(item, initialState); + doCommand(caption, command, initialState, data); + } + + protected <DATATYPE> void createClickAction(String caption, + String category, final Command<T, DATATYPE> command, DATATYPE value) { + createClickAction(caption, category, command, value, null); + } + + protected <DATATYPE> void createClickAction(String caption, + String category, final Command<T, DATATYPE> command, + DATATYPE value, Object data) { + MenuItem categoryItem = getCategoryMenuItem(category); + categoryItem.addItem(caption, menuClickCommand(command, value, data)); + } + + private MenuItem getCategoryMenuItem(String category) { + if (category == null) { + return getCategoryMenuItem("Misc"); + } + + MenuItem item = categoryToMenuItem.get(category); + if (item != null) { + return item; + } + + return createCategory(category, null); + } + + /** + * Creates category named "category" with id "categoryId" in parent category + * "parentCategory". Each categoryId must be globally unique. + * + * @param category + * @param categoryId + * @param parentCategory + * @return + */ + protected MenuItem createCategory(String category, String parentCategory) { + if (hasCategory(category)) { + return categoryToMenuItem.get(category); + } + MenuItem item; + if (parentCategory == null) { + item = mainMenu.addItem(category, null); + } else { + item = getCategoryMenuItem(parentCategory).addItem(category, null); + } + categoryToMenuItem.put(category, item); + menuItemToCategory.put(item, category); + return item; + } + + protected boolean hasCategory(String categoryId) { + return categoryToMenuItem.containsKey(categoryId); + } + + protected void removeCategory(String categoryId) { + if (!hasCategory(categoryId)) { + throw new IllegalArgumentException("Category '" + categoryId + + "' does not exist"); + } + + MenuItem item = getCategoryMenuItem(categoryId); + Object[] children = item.getChildren().toArray(); + for (Object child : children) { + if (menuItemToCategory.containsKey(child)) { + removeCategory(menuItemToCategory.get(child)); + } + } + // Detach from parent + item.getParent().removeChild(item); + // Clean mappings + categoryToMenuItem.remove(categoryId); + menuItemToCategory.remove(item); + + } + + private MenuBar.Command menuBooleanCommand( + final com.vaadin.tests.components.ComponentTestCase.Command<T, Boolean> booleanCommand, + final Object data) { + + return new MenuBar.Command() { + @Override + public void menuSelected(MenuItem selectedItem) { + boolean selected = !isSelected(selectedItem); + doCommand(getText(selectedItem), booleanCommand, selected, data); + setSelected(selectedItem, selected); + } + + }; + } + + private <DATATYPE> MenuBar.Command menuClickCommand( + final com.vaadin.tests.components.ComponentTestCase.Command<T, DATATYPE> command, + final DATATYPE value, final Object data) { + + return new MenuBar.Command() { + @Override + public void menuSelected(MenuItem selectedItem) { + doCommand(getText(selectedItem), command, value, data); + } + + }; + } + + protected void setSelected(MenuItem item, boolean selected) { + if (selected) { + item.setIcon(SELECTED_ICON); + } else { + item.setIcon(null); + } + } + + protected boolean isSelected(MenuItem item) { + return (item.getIcon() != null); + } + + private <VALUETYPE> MenuBar.Command singleSelectMenuCommand( + final com.vaadin.tests.components.ComponentTestCase.Command<T, VALUETYPE> cmd, + final VALUETYPE object, final Object data) { + return new MenuBar.Command() { + @Override + public void menuSelected(MenuItem selectedItem) { + doCommand(getText(selectedItem), cmd, object, data); + + if (parentOfSelectableMenuItem.contains(selectedItem + .getParent())) { + unselectChildren(selectedItem.getParent()); + setSelected(selectedItem, true); + } + } + + }; + + } + + /** + * Unselect all child menu items + * + * @param parent + */ + protected void unselectChildren(MenuItem parent) { + List<MenuItem> children = parent.getChildren(); + if (children == null) { + return; + } + + for (MenuItem child : children) { + setSelected(child, false); + } + } + + protected String getText(MenuItem item) { + String path = ""; + MenuItem parent = item.getParent(); + while (!isCategory(parent)) { + path = parent.getText() + "/" + path; + parent = parent.getParent(); + } + + return path + "/" + item.getText(); + } + + private boolean isCategory(MenuItem item) { + return item.getParent() == mainMenu; + } + + protected <TYPE> void createSelectAction( + String caption, + String category, + LinkedHashMap<String, TYPE> options, + String initialValue, + com.vaadin.tests.components.ComponentTestCase.Command<T, TYPE> command) { + createSelectAction(caption, category, options, initialValue, command, + null); + + } + + protected <TYPE> void createMultiClickAction( + String caption, + String category, + LinkedHashMap<String, TYPE> options, + com.vaadin.tests.components.ComponentTestCase.Command<T, TYPE> command, + Object data) { + + MenuItem categoryItem = getCategoryMenuItem(category); + MenuItem mainItem = categoryItem.addItem(caption, null); + + for (String option : options.keySet()) { + MenuBar.Command cmd = menuClickCommand(command, + options.get(option), data); + mainItem.addItem(option, cmd); + } + } + + protected <TYPE> void createMultiToggleAction( + String caption, + String category, + LinkedHashMap<String, TYPE> options, + com.vaadin.tests.components.ComponentTestCase.Command<T, Boolean> command, + boolean defaultValue) { + + LinkedHashMap<String, Boolean> defaultValues = new LinkedHashMap<String, Boolean>(); + + for (String option : options.keySet()) { + defaultValues.put(option, defaultValue); + } + + createMultiToggleAction(caption, category, options, command, + defaultValues); + } + + protected <TYPE> void createMultiToggleAction( + String caption, + String category, + LinkedHashMap<String, TYPE> options, + com.vaadin.tests.components.ComponentTestCase.Command<T, Boolean> command, + LinkedHashMap<String, Boolean> defaultValues) { + + createCategory(caption, category); + + for (String option : options.keySet()) { + createBooleanAction(option, caption, defaultValues.get(option), + command, options.get(option)); + + } + } + + protected <TYPE> void createSelectAction( + String caption, + String category, + LinkedHashMap<String, TYPE> options, + String initialValue, + com.vaadin.tests.components.ComponentTestCase.Command<T, TYPE> command, + Object data) { + + MenuItem parentItem = getCategoryMenuItem(category); + MenuItem mainItem = parentItem.addItem(caption, null); + + parentOfSelectableMenuItem.add(mainItem); + for (String option : options.keySet()) { + MenuBar.Command cmd = singleSelectMenuCommand(command, + options.get(option), data); + MenuItem item = mainItem.addItem(option, cmd); + if (option.equals(initialValue)) { + cmd.menuSelected(item); + } + } + } + + protected LinkedHashMap<String, Integer> createIntegerOptions(int max) { + LinkedHashMap<String, Integer> options = new LinkedHashMap<String, Integer>(); + for (int i = 0; i <= 9 && i <= max; i++) { + options.put(String.valueOf(i), i); + } + for (int i = 10; i <= max; i *= 10) { + options.put(String.valueOf(i), i); + if (2 * i <= max) { + options.put(String.valueOf(2 * i), 2 * i); + } + if (5 * i <= max) { + options.put(String.valueOf(5 * i), 5 * i); + } + } + + return options; + } + + protected LinkedHashMap<String, Double> createDoubleOptions(double max) { + LinkedHashMap<String, Double> options = new LinkedHashMap<String, Double>(); + for (double d = 0; d <= max && d < 10; d += 0.5) { + options.put(String.valueOf(d), d); + } + for (double d = 10; d <= max; d *= 10) { + options.put(String.valueOf(d), d); + if (2.5 * d <= max) { + options.put(String.valueOf(2 * d), 2 * d); + } + if (5 * d <= max) { + options.put(String.valueOf(5 * d), 5 * d); + } + } + + return options; + } + + protected LinkedHashMap<String, Resource> createIconOptions( + boolean cacheable) { + LinkedHashMap<String, Resource> options = new LinkedHashMap<String, Resource>(); + options.put("-", null); + if (cacheable) { + options.put("16x16", ICON_16_USER_PNG_CACHEABLE); + options.put("32x32", ICON_32_ATTENTION_PNG_CACHEABLE); + options.put("64x64", ICON_64_EMAIL_REPLY_PNG_CACHEABLE); + } else { + options.put("16x16", ICON_16_USER_PNG_UNCACHEABLE); + options.put("32x32", ICON_32_ATTENTION_PNG_UNCACHEABLE); + options.put("64x64", ICON_64_EMAIL_REPLY_PNG_UNCACHEABLE); + + } + return options; + } + + protected void log(String msg) { + log.log(msg); + } + + protected boolean hasLog() { + return log != null; + } + + @Override + protected <VALUET> void doCommand(String commandName, + AbstractComponentTestCase.Command<T, VALUET> command, VALUET value, + Object data) { + if (hasLog()) { + log("Command: " + commandName + "(" + value + ")"); + } + super.doCommand(commandName, command, value, data); + } + + @Override + public void terminalError(com.vaadin.server.Terminal.ErrorEvent event) { + String logMsg = "Exception occured, " + + event.getThrowable().getClass().getName(); + + String exceptionMsg = event.getThrowable().getMessage(); + if (exceptionMsg != null && exceptionMsg.length() > 0) { + logMsg += exceptionMsg; + } + log.log(logMsg); + final Throwable t = event.getThrowable(); + if (t != null) { + t.printStackTrace(); + } + + } + + @Override + public void focus(FocusEvent event) { + log(event.getClass().getSimpleName()); + } + + @Override + public void blur(BlurEvent event) { + log(event.getClass().getSimpleName()); + } + +} |