diff options
34 files changed, 1167 insertions, 182 deletions
diff --git a/WebContent/VAADIN/themes/base/common/common.scss b/WebContent/VAADIN/themes/base/common/common.scss index 07e244a76f..5cae1b26ce 100644 --- a/WebContent/VAADIN/themes/base/common/common.scss +++ b/WebContent/VAADIN/themes/base/common/common.scss @@ -227,6 +227,10 @@ input::-ms-clear { font-size: 0; line-height: normal; } +/* Set font-size in order to make Firefox scrolling better #11353 */ +.v-ff & .v-scrollable { + font-size: $font-size; +} .v-ios.v-webkit & .v-scrollable { -webkit-overflow-scrolling: touch; } diff --git a/all/build.xml b/all/build.xml index 1b48721ecd..36a9499dea 100644 --- a/all/build.xml +++ b/all/build.xml @@ -43,7 +43,8 @@ <property name="javadoc.dir" location="${result.dir}/javadoc" /> <property name="title" value="Vaadin ${vaadin.version} API" /> - <javadoc maxmemory="1024m" destdir="${javadoc.dir}" author="true" version="true" use="true" windowtitle="${title}" encoding="utf-8"> + <javadoc maxmemory="1024m" destdir="${javadoc.dir}" author="true" version="true" use="true" windowtitle="${title}" encoding="utf-8" + stylesheetfile="javadoc.css"> <packageset dir="${javadoc.temp.dir}"> <!-- TODO Javadoc throws ClassCastException if this is included (#9660) --> diff --git a/all/javadoc.css b/all/javadoc.css new file mode 100644 index 0000000000..ffa7288ad4 --- /dev/null +++ b/all/javadoc.css @@ -0,0 +1,236 @@ +@charset "UTF-8"; + +/* + * stylesheet for Vaadin Javadoc when compiled with Java 6 + */ +body { + background-color: rgb(244, 244, 240); + color: rgb(70, 68, 64); + font-size: 16px; + font-family: Helvetica, Arial, sans-serif; + font-weight: lighter; + line-height: 18px; + margin: 10px 14px; +} + +body[onload] { + background-color: rgb(255, 255, 255); + margin: 8px 23px; +} + +a:link,a:visited { + color: rgb(0, 180, 240); + text-decoration: none; +} + +b { + font-weight: bolder; +} + +code,pre { + font-family: Courier, monospace; +} + +dt { + font-size: 12px; + color: rgb(120, 119, 109); + text-transform: uppercase; +} + +dd>dl>dt { + font-size: 13px; + text-transform: none; +} + +h2+dl>dt { + text-transform: none; +} + +dt>pre,pre>dt { + text-transform: initial; +} + +dd { + font-size: 14px; + margin-left: 2.5em; +} + +dd:first-child { + font-size: 13px; +} + +dd>dl>dd { + font-size: 12px; +} + +h1 { + font-size: 32px +} + +h2 { + font-size: 24px; +} + +h3 { + font-size: 16px; +} + +h1,h2,h3 { + line-height: 30px; +} + +hr { + border: 1px solid rgb(233, 233, 225); +} + +pre,h2+ul { + font-size: 12px; +} + +table { + border: none; + border-collapse: collapse; +} + +td { + padding: 0; +} + +th { + padding: 0 1ch; +} + +.TableHeadingColor,.TableSubHeadingColor { + line-height: 30px; +} + +.TableHeadingColor>th,.TableHeadingColor>th>font>b,.TableSubHeadingColor>th,.TableSubHeadingColor>th>b + { + font-weight: inherit; +} + +.TableHeadingColor>th>font { + font-size: 18px; +} + +.TableSubHeadingColor { + font-size: 14px; +} + +.TableHeadingColor,.TableSubHeadingColor { + background: rgb(233, 233, 225); +} + +.TableRowColor { + background: #FFFFFF; +} + +.TableRowColor:nth-child(odd) { + background-color: rgb(244, 244, 240); +} + +.TableRowColor>td { + font-size: 12px; + border: none; + padding: 1ex 1ch +} + +.TableRowColor>td>font { + font-size: 11px; +} + +.TableHeadingColor,.TableRowColor,.TableSubHeadingColor>th { + border: none; + border-color: transparent; +} + +table[border="1"] { + border: 2px solid rgb(233, 233, 225); +} + +.FrameTitleFont { + font-size: 18px; + font-family: Helvetica, Arial, sans-serif; + font-weight: bolder; + line-height: 30px; +} + +.FrameHeadingFont { + font-size: 12px; + font-family: Helvetica, Arial, sans-serif; + font-weight: bold; + color: rgb(120, 119, 109); + text-transform: uppercase; + display: inline-block; + margin-bottom: 4px; +} + +td>.FrameHeadingFont { + margin-top: 12px; +} + +.FrameItemFont { + font-size: 90%; + font-family: Helvetica, Arial, sans-serif; +} + +.NavBarCell1 { + background-color: rgb(245, 245, 241); + border: 2px solid rgb(245, 245, 241); +} + +.NavBarCell1+td[rowspan="3"] { + display: none; +} + +.NavBarCell1,.NavBarCell1Rev { + font-size: 0; +} + +.NavBarCell1>*,.NavBarCell1Rev>* { + font-size: 14px; +} + +.NavBarCell1 .NavBarCell1,.NavBarCell1 .NavBarCell1Rev { + padding: 3px 8px; + line-height: 1; + vertical-align: baseline; +} + +.NavBarCell1Rev { + background-color: rgb(0, 180, 240); + border-radius: 3px; +} + +.NavBarFont1 { + font-family: Helvetica, Arial, sans-serif; + color: rgb(70, 68, 64); +} + +.NavBarFont1Rev { + font-family: Helvetica, Arial, sans-serif; + color: rgb(255, 255, 255); +} + +.NavBarCell2 { + font-family: Helvetica, Arial, sans-serif; + background-color: #FFFFFF; + padding-top: 6px; +} + +.NavBarCell2:first-child { + color: transparent; +} + +.NavBarCell2>font,.NavBarCell3>font { + font-size: 11px; +} + +.NavBarCell2>font>a>b { + font-weight: normal; +} + +.NavBarCell3 { + font-family: Helvetica, Arial, sans-serif; + background-color: #FFFFFF; +}
\ No newline at end of file @@ -19,6 +19,7 @@ <fileset dir="." includes="**/build.xml"> <exclude name="build.xml" /> <exclude name="build/**" /> + <exclude name="bin/**" /> <exclude name="buildhelpers/**" /> </fileset> </ivy:buildlist> diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java index 3a7e15626a..10dbc71901 100644 --- a/client/src/com/vaadin/client/ui/VScrollTable.java +++ b/client/src/com/vaadin/client/ui/VScrollTable.java @@ -1060,6 +1060,8 @@ public class VScrollTable extends FlowPanel implements HasWidgets, if (uidl.hasVariable("selected")) { final Set<String> selectedKeys = uidl .getStringArrayVariableAsSet("selected"); + removeUnselectedRowKeys(selectedKeys); + if (scrollBody != null) { Iterator<Widget> iterator = scrollBody.iterator(); while (iterator.hasNext()) { @@ -1102,6 +1104,16 @@ public class VScrollTable extends FlowPanel implements HasWidgets, return keyboardSelectionOverRowFetchInProgress; } + private void removeUnselectedRowKeys(final Set<String> selectedKeys) { + List<String> unselectedKeys = new ArrayList<String>(0); + for (String key : selectedRowKeys) { + if (!selectedKeys.contains(key)) { + unselectedKeys.add(key); + } + } + selectedRowKeys.removeAll(unselectedKeys); + } + /** For internal use only. May be removed or replaced in the future. */ public void updateSortingProperties(UIDL uidl) { oldSortColumn = sortColumn; diff --git a/client/src/com/vaadin/client/ui/VTabsheet.java b/client/src/com/vaadin/client/ui/VTabsheet.java index 34904405c7..82eb9e7694 100644 --- a/client/src/com/vaadin/client/ui/VTabsheet.java +++ b/client/src/com/vaadin/client/ui/VTabsheet.java @@ -948,8 +948,8 @@ public class VTabsheet extends VTabsheetBase implements Focusable, tab = tb.addTab(); } if (selected) { - renderContent(tabUidl.getChildUIDL(0)); tb.selectTab(index); + renderContent(tabUidl.getChildUIDL(0)); } tab.updateFromUIDL(tabUidl); tab.setEnabledOnServer((!disabledTabKeys.contains(tabKeys.get(index)))); diff --git a/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java b/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java index f91ff9e2b9..8dec26cf90 100644 --- a/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java +++ b/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java @@ -37,6 +37,10 @@ import com.vaadin.ui.ComboBox; public class ComboBoxConnector extends AbstractFieldConnector implements Paintable, SimpleManagedLayout { + // oldSuggestionTextMatchTheOldSelection is used to detect when it's safe to + // update textbox text by a changed item caption. + private boolean oldSuggestionTextMatchTheOldSelection; + /* * (non-Javadoc) * @@ -117,7 +121,10 @@ public class ComboBoxConnector extends AbstractFieldConnector implements boolean suggestionsChanged = !getWidget().initDone || !newSuggestions.equals(getWidget().currentSuggestions); + oldSuggestionTextMatchTheOldSelection = false; + if (suggestionsChanged) { + oldSuggestionTextMatchTheOldSelection = isWidgetsCurrentSelectionTextInTextBox(); getWidget().currentSuggestions.clear(); if (!getWidget().waitingForFilteringResponse) { @@ -212,29 +219,38 @@ public class ComboBoxConnector extends AbstractFieldConnector implements // some item selected for (FilterSelectSuggestion suggestion : getWidget().currentSuggestions) { String suggestionKey = suggestion.getOptionKey(); - if (suggestionKey.equals(selectedKey)) { - if (!getWidget().waitingForFilteringResponse - || getWidget().popupOpenerClicked) { - if (!suggestionKey.equals(getWidget().selectedOptionKey) - || suggestion.getReplacementString().equals( - getWidget().tb.getText())) { - // Update text field if we've got a new - // selection - // Also update if we've got the same text to - // retain old text selection behavior - getWidget().setPromptingOff( - suggestion.getReplacementString()); - getWidget().selectedOptionKey = suggestionKey; - } + if (!suggestionKey.equals(selectedKey)) { + continue; + } + if (!getWidget().waitingForFilteringResponse + || getWidget().popupOpenerClicked) { + if (!suggestionKey.equals(getWidget().selectedOptionKey) + || suggestion.getReplacementString().equals( + getWidget().tb.getText()) + || oldSuggestionTextMatchTheOldSelection) { + // Update text field if we've got a new + // selection + // Also update if we've got the same text to + // retain old text selection behavior + // OR if selected item caption is changed. + getWidget().setPromptingOff( + suggestion.getReplacementString()); + getWidget().selectedOptionKey = suggestionKey; } - getWidget().currentSuggestion = suggestion; - getWidget().setSelectedItemIcon(suggestion.getIconUri()); - // only a single item can be selected - break; } + getWidget().currentSuggestion = suggestion; + getWidget().setSelectedItemIcon(suggestion.getIconUri()); + // only a single item can be selected + break; } } + private boolean isWidgetsCurrentSelectionTextInTextBox() { + return getWidget().currentSuggestion != null + && getWidget().currentSuggestion.getReplacementString().equals( + getWidget().tb.getText()); + } + private void resetSelection() { if (!getWidget().waitingForFilteringResponse || getWidget().popupOpenerClicked) { diff --git a/client/src/com/vaadin/client/ui/orderedlayout/Slot.java b/client/src/com/vaadin/client/ui/orderedlayout/Slot.java index 49b3661431..37a97f3399 100644 --- a/client/src/com/vaadin/client/ui/orderedlayout/Slot.java +++ b/client/src/com/vaadin/client/ui/orderedlayout/Slot.java @@ -19,9 +19,11 @@ package com.vaadin.client.ui.orderedlayout; import java.util.List; import com.google.gwt.aria.client.Roles; +import com.google.gwt.dom.client.Document; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.UIObject; import com.google.gwt.user.client.ui.Widget; @@ -456,6 +458,9 @@ public final class Slot extends SimplePanel { // Caption wrappers Widget widget = getWidget(); + final Element focusedElement = Util.getFocusedElement(); + // By default focus will not be lost + boolean focusLost = false; if (captionText != null || iconUrl != null || error != null || required) { if (caption == null) { caption = DOM.createDiv(); @@ -466,6 +471,10 @@ public final class Slot extends SimplePanel { orphan(widget); captionWrap.appendChild(widget.getElement()); adopt(widget); + + // Made changes to DOM. Focus can be lost if it was in the + // widget. + focusLost = widget.getElement().isOrHasChild(focusedElement); } } else if (caption != null) { orphan(widget); @@ -474,6 +483,9 @@ public final class Slot extends SimplePanel { captionWrap.removeFromParent(); caption = null; captionWrap = null; + + // Made changes to DOM. Focus can be lost if it was in the widget. + focusLost = widget.getElement().isOrHasChild(focusedElement); } // Caption text @@ -560,6 +572,45 @@ public final class Slot extends SimplePanel { setCaptionPosition(CaptionPosition.RIGHT); } } + + if (focusLost) { + // Find out what element is currently focused. + Element currentFocus = Util.getFocusedElement(); + if (currentFocus != null + && currentFocus.equals(Document.get().getBody())) { + // Focus has moved to BodyElement and should be moved back to + // original location. This happened because of adding or + // removing the captionWrap + focusedElement.focus(); + } else if (currentFocus != focusedElement) { + // Focus is either moved somewhere else on purpose or IE has + // lost it. Investigate further. + Timer focusTimer = new Timer() { + + @Override + public void run() { + if (Util.getFocusedElement() == null) { + // This should never become an infinite loop and + // even if it does it will be stopped once something + // is done with the browser. + schedule(25); + } else if (Util.getFocusedElement().equals( + Document.get().getBody())) { + // Focus found it's way to BodyElement. Now it can + // be restored + focusedElement.focus(); + } + } + }; + if (BrowserInfo.get().isIE8()) { + // IE8 can't fix the focus immediately. It will fail. + focusTimer.schedule(25); + } else { + // Newer IE versions can handle things immediately. + focusTimer.run(); + } + } + } } /** diff --git a/server/src/com/vaadin/data/Buffered.java b/server/src/com/vaadin/data/Buffered.java index 0d6722f71f..c4c79ae13f 100644 --- a/server/src/com/vaadin/data/Buffered.java +++ b/server/src/com/vaadin/data/Buffered.java @@ -23,29 +23,20 @@ import com.vaadin.data.Validator.InvalidValueException; /** * <p> * Defines the interface to commit and discard changes to an object, supporting - * read-through and write-through modes. - * </p> + * buffering. * * <p> - * <i>Read-through mode</i> means that the value read from the buffered object - * is constantly up to date with the data source. <i>Write-through</i> mode - * means that all changes to the object are immediately updated to the data - * source. - * </p> + * In <i>buffered</i> mode the initial value is read from the data source and + * then buffered. Any subsequential writes or reads will be done on the buffered + * value. Calling {@link #commit()} will write the buffered value to the data + * source while calling {@link #discard()} while discard the buffered value and + * re-read the value from the data source. * * <p> - * Since these modes are independent, their combinations may result in some - * behaviour that may sound surprising. - * </p> - * - * <p> - * For example, if a <code>Buffered</code> object is in read-through mode but - * not in write-through mode, the result is an object whose value is updated - * directly from the data source only if it's not locally modified. If the value - * is locally modified, retrieving the value from the object would result in a - * value that is different than the one stored in the data source, even though - * the object is in read-through mode. - * </p> + * In <i>non-buffered</i> mode the value is always read directly from the data + * source. Any write is done directly to the data source with no buffering in + * between. Reads are also done directly from the data source. Calling + * {@link #commit()} or {@link #discard()} in this mode is efficiently a no-op. * * @author Vaadin Ltd. * @since 3.0 @@ -77,25 +68,15 @@ public interface Buffered extends Serializable { public void discard() throws SourceException; /** - * Sets the object's buffered mode to the specified status. + * Sets the buffered mode to the specified status. * <p> - * When the object is in buffered mode, an internal buffer will be used to - * store changes until {@link #commit()} is called. Calling - * {@link #discard()} will revert the internal buffer to the value of the - * data source. - * </p> + * When in buffered mode, an internal buffer will be used to store changes + * until {@link #commit()} is called. Calling {@link #discard()} will revert + * the internal buffer to the value of the data source. * <p> - * This is an easier way to use {@link #setReadThrough(boolean)} and - * {@link #setWriteThrough(boolean)} and not as error prone. Changing - * buffered mode will change both the read through and write through state - * of the object. - * </p> - * <p> - * Mixing calls to {@link #setBuffered(boolean)}/{@link #isBuffered()} and - * {@link #setReadThrough(boolean)}/{@link #isReadThrough()} or - * {@link #setWriteThrough(boolean)}/{@link #isWriteThrough()} is generally - * a bad idea. - * </p> + * When in non-buffered mode both read and write operations will be done + * directly on the data source. In this mode the {@link #commit()} and + * {@link #discard()} methods serve no purpose. * * @param buffered * true if buffered mode should be turned on, false otherwise @@ -104,10 +85,7 @@ public interface Buffered extends Serializable { public void setBuffered(boolean buffered); /** - * Checks the buffered mode of this Object. - * <p> - * This method only returns true if both read and write buffering is used. - * </p> + * Checks the buffered mode * * @return true if buffered mode is on, false otherwise * @since 7.0 diff --git a/server/src/com/vaadin/data/util/filter/Between.java b/server/src/com/vaadin/data/util/filter/Between.java index 8209f7b0a2..a76821981a 100644 --- a/server/src/com/vaadin/data/util/filter/Between.java +++ b/server/src/com/vaadin/data/util/filter/Between.java @@ -67,6 +67,10 @@ public class Between implements Filter { @Override public boolean equals(Object obj) { + if (obj == null) { + return false; + } + // Only objects of the same class can be equal if (!getClass().equals(obj.getClass())) { return false; diff --git a/server/src/com/vaadin/data/util/filter/Compare.java b/server/src/com/vaadin/data/util/filter/Compare.java index f9f19c6602..ac167673bd 100644 --- a/server/src/com/vaadin/data/util/filter/Compare.java +++ b/server/src/com/vaadin/data/util/filter/Compare.java @@ -307,6 +307,9 @@ public abstract class Compare implements Filter { @Override public boolean equals(Object obj) { + if (obj == null) { + return false; + } // Only objects of the same class can be equal if (!getClass().equals(obj.getClass())) { diff --git a/server/src/com/vaadin/data/util/filter/IsNull.java b/server/src/com/vaadin/data/util/filter/IsNull.java index 5c5bdfc0b1..6907a016a1 100644 --- a/server/src/com/vaadin/data/util/filter/IsNull.java +++ b/server/src/com/vaadin/data/util/filter/IsNull.java @@ -62,6 +62,10 @@ public final class IsNull implements Filter { @Override public boolean equals(Object obj) { + if (obj == null) { + return false; + } + // Only objects of the same class can be equal if (!getClass().equals(obj.getClass())) { return false; diff --git a/server/src/com/vaadin/data/util/filter/Like.java b/server/src/com/vaadin/data/util/filter/Like.java index 4c15564105..dc2e18363a 100644 --- a/server/src/com/vaadin/data/util/filter/Like.java +++ b/server/src/com/vaadin/data/util/filter/Like.java @@ -84,6 +84,10 @@ public class Like implements Filter { @Override public boolean equals(Object obj) { + if (obj == null) { + return false; + } + // Only objects of the same class can be equal if (!getClass().equals(obj.getClass())) { return false; diff --git a/server/src/com/vaadin/data/util/filter/SimpleStringFilter.java b/server/src/com/vaadin/data/util/filter/SimpleStringFilter.java index bc58999445..a214e69846 100644 --- a/server/src/com/vaadin/data/util/filter/SimpleStringFilter.java +++ b/server/src/com/vaadin/data/util/filter/SimpleStringFilter.java @@ -82,6 +82,9 @@ public final class SimpleStringFilter implements Filter { @Override public boolean equals(Object obj) { + if (obj == null) { + return false; + } // Only ones of the objects of the same class can be equal if (!(obj instanceof SimpleStringFilter)) { diff --git a/server/src/com/vaadin/server/widgetsetutils/ClassPathExplorer.java b/server/src/com/vaadin/server/widgetsetutils/ClassPathExplorer.java index cc04e50b3c..3ad76794de 100644 --- a/server/src/com/vaadin/server/widgetsetutils/ClassPathExplorer.java +++ b/server/src/com/vaadin/server/widgetsetutils/ClassPathExplorer.java @@ -32,8 +32,6 @@ import java.util.Set; import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; -import java.util.logging.Level; -import java.util.logging.Logger; /** * Utility class to collect widgetset related information from classpath. @@ -111,6 +109,15 @@ public class ClassPathExplorer { */ private static Map<String, URL> classpathLocations = getClasspathLocations(rawClasspathEntries); + private static boolean debug = false; + + static { + String debugProperty = System.getProperty("debug"); + if (debugProperty != null && !debugProperty.equals("")) { + debug = true; + } + } + /** * No instantiation from outside, callable methods are static. */ @@ -163,9 +170,8 @@ public class ClassPathExplorer { sb.append("\n"); } - final Logger logger = getLogger(); - logger.info(sb.toString()); - logger.info("Search took " + (end - start) + "ms"); + log(sb.toString()); + log("Search took " + (end - start) + "ms"); return new LocationInfo(widgetsets, themes); } @@ -226,8 +232,7 @@ public class ClassPathExplorer { } catch (MalformedURLException e) { // should never happen as based on an existing URL, // only changing end of file name/path part - getLogger().log(Level.SEVERE, - "Error locating the widgetset " + classname, e); + error("Error locating the widgetset " + classname, e); } } } @@ -276,7 +281,7 @@ public class ClassPathExplorer { } } } catch (IOException e) { - getLogger().log(Level.WARNING, "Error parsing jar file", e); + error("Error parsing jar file", e); } } @@ -304,7 +309,7 @@ public class ClassPathExplorer { classpath = classpath.substring(0, classpath.length() - 1); } - getLogger().log(Level.FINE, "Classpath: {0}", classpath); + debug("Classpath: " + classpath); String[] split = classpath.split(pathSep); for (int i = 0; i < split.length; i++) { @@ -338,9 +343,8 @@ public class ClassPathExplorer { include(null, file, locations); } long end = System.currentTimeMillis(); - Logger logger = getLogger(); - if (logger.isLoggable(Level.FINE)) { - logger.fine("getClassPathLocations took " + (end - start) + "ms"); + if (debug) { + debug("getClassPathLocations took " + (end - start) + "ms"); } return locations; } @@ -379,7 +383,8 @@ public class ClassPathExplorer { url = new URL("jar:" + url.toExternalForm() + "!/"); JarURLConnection conn = (JarURLConnection) url .openConnection(); - getLogger().fine(url.toString()); + debug(url.toString()); + JarFile jarFile = conn.getJarFile(); Manifest manifest = jarFile.getManifest(); if (manifest != null) { @@ -393,11 +398,13 @@ public class ClassPathExplorer { } } } catch (MalformedURLException e) { - getLogger().log(Level.FINEST, "Failed to inspect JAR file", - e); + if (debug) { + error("Failed to inspect JAR file", e); + } } catch (IOException e) { - getLogger().log(Level.FINEST, "Failed to inspect JAR file", - e); + if (debug) { + error("Failed to inspect JAR file", e); + } } return false; @@ -489,14 +496,12 @@ public class ClassPathExplorer { */ public static URL getDefaultSourceDirectory() { - final Logger logger = getLogger(); - - if (logger.isLoggable(Level.FINE)) { - logger.fine("classpathLocations values:"); + if (debug) { + debug("classpathLocations values:"); ArrayList<String> locations = new ArrayList<String>( classpathLocations.keySet()); for (String location : locations) { - logger.fine(String.valueOf(classpathLocations.get(location))); + debug(String.valueOf(classpathLocations.get(location))); } } @@ -510,11 +515,15 @@ public class ClassPathExplorer { try { return new URL("file://" + directory.getCanonicalPath()); } catch (MalformedURLException e) { - logger.log(Level.FINEST, "Ignoring exception", e); // ignore: continue to the next classpath entry + if (debug) { + e.printStackTrace(); + } } catch (IOException e) { - logger.log(Level.FINEST, "Ignoring exception", e); // ignore: continue to the next classpath entry + if (debug) { + e.printStackTrace(); + } } } } @@ -525,14 +534,24 @@ public class ClassPathExplorer { * Test method for helper tool */ public static void main(String[] args) { - getLogger().info( - "Searching for available widgetsets and stylesheets..."); + log("Searching for available widgetsets and stylesheets..."); ClassPathExplorer.getAvailableWidgetSetsAndStylesheets(); } - private static final Logger getLogger() { - return Logger.getLogger(ClassPathExplorer.class.getName()); + private static void log(String message) { + System.out.println(message); + } + + private static void error(String message, Exception e) { + System.err.println(message); + e.printStackTrace(); + } + + private static void debug(String message) { + if (debug) { + System.out.println(message); + } } } diff --git a/server/src/com/vaadin/ui/Calendar.java b/server/src/com/vaadin/ui/Calendar.java index 9ccc8ea2d9..b0999451c3 100644 --- a/server/src/com/vaadin/ui/Calendar.java +++ b/server/src/com/vaadin/ui/Calendar.java @@ -1824,7 +1824,7 @@ public class Calendar extends AbstractComponent implements try { Date start = formatter.parse(startDate); for (Action.Handler ah : actionHandlers) { - ah.handleAction(action, this, start); + ah.handleAction(action, Calendar.this, start); } } catch (ParseException e) { @@ -1842,7 +1842,7 @@ public class Calendar extends AbstractComponent implements DateConstants.ACTION_DATE_FORMAT_PATTERN); formatter.setTimeZone(getTimeZone()); for (Action.Handler ah : actionHandlers) { - ah.handleAction(action, this, events.get(eventIndex)); + ah.handleAction(action, Calendar.this, events.get(eventIndex)); } } } diff --git a/server/src/com/vaadin/ui/FormLayout.java b/server/src/com/vaadin/ui/FormLayout.java index 9d5e637068..9dc0b24cad 100644 --- a/server/src/com/vaadin/ui/FormLayout.java +++ b/server/src/com/vaadin/ui/FormLayout.java @@ -52,4 +52,23 @@ public class FormLayout extends AbstractOrderedLayout { addComponents(children); } + /** + * @deprecated This method currently has no effect as expand ratios are not + * implemented in FormLayout + */ + @Override + @Deprecated + public void setExpandRatio(Component component, float ratio) { + super.setExpandRatio(component, ratio); + } + + /** + * @deprecated This method currently has no effect as expand ratios are not + * implemented in FormLayout + */ + @Override + @Deprecated + public float getExpandRatio(Component component) { + return super.getExpandRatio(component); + } } diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/filters/CompareTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/filters/CompareTest.java new file mode 100644 index 0000000000..c8faa71e66 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/filters/CompareTest.java @@ -0,0 +1,44 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * 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. + */ +package com.vaadin.data.util.sqlcontainer.filters; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.util.filter.Compare; + +public class CompareTest { + + @Test + public void testEquals() { + Compare c1 = new Compare.Equal("prop1", "val1"); + Compare c2 = new Compare.Equal("prop1", "val1"); + Assert.assertTrue(c1.equals(c2)); + } + + @Test + public void testDifferentTypeEquals() { + Compare c1 = new Compare.Equal("prop1", "val1"); + Compare c2 = new Compare.Greater("prop1", "val1"); + Assert.assertFalse(c1.equals(c2)); + } + + @Test + public void testEqualsNull() { + Compare c1 = new Compare.Equal("prop1", "val1"); + Assert.assertFalse(c1.equals(null)); + } +} diff --git a/uitest/src/com/vaadin/tests/applicationservlet/NoApplicationClass.java b/uitest/src/com/vaadin/tests/applicationservlet/NoApplicationClassTest.java index c2222c4608..9d1b052182 100644 --- a/uitest/src/com/vaadin/tests/applicationservlet/NoApplicationClass.java +++ b/uitest/src/com/vaadin/tests/applicationservlet/NoApplicationClassTest.java @@ -25,7 +25,7 @@ import org.openqa.selenium.remote.DesiredCapabilities; import com.vaadin.tests.tb3.MultiBrowserTest; -public class NoApplicationClass extends MultiBrowserTest { +public class NoApplicationClassTest extends MultiBrowserTest { @Test public void testInvalidApplicationClass() { @@ -33,7 +33,7 @@ public class NoApplicationClass extends MultiBrowserTest { String exceptionMessage = getDriver().findElement(By.xpath("//pre[2]")) .getText(); Assert.assertTrue(exceptionMessage - .contains("ServletException: ClassThatIsNotPresent")); + .contains("ServletException: java.lang.ClassNotFoundException: ClassThatIsNotPresent")); } @Override diff --git a/uitest/src/com/vaadin/tests/components/UnknownComponentConnector.java b/uitest/src/com/vaadin/tests/components/UnknownComponentConnector.java new file mode 100644 index 0000000000..b6358b6c56 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/UnknownComponentConnector.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * 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. + */ + +package com.vaadin.tests.components; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.ui.AbstractComponent; + +public class UnknownComponentConnector extends AbstractTestUI { + + public static class ComponentWithoutConnector extends AbstractComponent { + + } + + @Override + protected void setup(VaadinRequest request) { + ComponentWithoutConnector component = new ComponentWithoutConnector(); + component.setId("no-connector-component"); + addComponent(component); + } + + @Override + protected String getTestDescription() { + // TODO Auto-generated method stub + return null; + } + + @Override + protected Integer getTicketNumber() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/UnknownComponentConnectorTest.html b/uitest/src/com/vaadin/tests/components/UnknownComponentConnectorTest.html deleted file mode 100644 index 20f0e8e71e..0000000000 --- a/uitest/src/com/vaadin/tests/components/UnknownComponentConnectorTest.html +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="" /> -<title>New Test</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">New Test</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.components.UnknownComponentConnectorTest?restartApplication</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestscomponentsUnknownComponentConnectorTest::/VVerticalLayout[0]/VVerticalLayout[0]/VUnknownComponent[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td> - <td>Widgetset does not contain implementation for com.vaadin.tests.components.UnknownComponentConnectorTest.ComponentWithoutConnector. Check its component connector's @Connect mapping, widgetsets GWT module description file and re-compile your widgetset. In case you have downloaded a vaadin add-on package, you might want to refer to add-on instructions.</td> -</tr> - -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/components/UnknownComponentConnectorTest.java b/uitest/src/com/vaadin/tests/components/UnknownComponentConnectorTest.java index ff113d631e..49a3c29e2d 100644 --- a/uitest/src/com/vaadin/tests/components/UnknownComponentConnectorTest.java +++ b/uitest/src/com/vaadin/tests/components/UnknownComponentConnectorTest.java @@ -13,33 +13,29 @@ * License for the specific language governing permissions and limitations under * the License. */ - package com.vaadin.tests.components; -import com.vaadin.server.VaadinRequest; -import com.vaadin.ui.AbstractComponent; - -public class UnknownComponentConnectorTest extends AbstractTestUI { +import static org.junit.Assert.assertTrue; - public static class ComponentWithoutConnector extends AbstractComponent { +import org.junit.Test; +import org.openqa.selenium.WebElement; - } - - @Override - protected void setup(VaadinRequest request) { - addComponent(new ComponentWithoutConnector()); - } +import com.vaadin.tests.tb3.MultiBrowserTest; - @Override - protected String getTestDescription() { - // TODO Auto-generated method stub - return null; - } - - @Override - protected Integer getTicketNumber() { - // TODO Auto-generated method stub - return null; +/** + * Tests that a user is notified about a missing component from the widgetset + */ +public class UnknownComponentConnectorTest extends MultiBrowserTest { + + @Test + public void testConnectorNotFoundInWidgetset() throws Exception { + openTestURL(); + WebElement component = vaadinElementById("no-connector-component"); + assertTrue(component + .getText() + .startsWith( + "Widgetset 'com.vaadin.DefaultWidgetSet' does not contain " + + "implementation for com.vaadin.tests.components.UnknownComponentConnector." + + "ComponentWithoutConnector.")); } - } diff --git a/uitest/src/com/vaadin/tests/components/calendar/CalendarActionEventSource.java b/uitest/src/com/vaadin/tests/components/calendar/CalendarActionEventSource.java new file mode 100644 index 0000000000..5e81750e58 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/calendar/CalendarActionEventSource.java @@ -0,0 +1,114 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * 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. + */ +package com.vaadin.tests.components.calendar; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import com.vaadin.event.Action; +import com.vaadin.event.Action.Handler; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Calendar; +import com.vaadin.ui.Calendar.TimeFormat; +import com.vaadin.ui.Label; +import com.vaadin.ui.components.calendar.CalendarComponentEvents.EventResizeHandler; +import com.vaadin.ui.components.calendar.event.BasicEvent; +import com.vaadin.ui.components.calendar.event.CalendarEvent; +import com.vaadin.ui.components.calendar.event.CalendarEventProvider; + +public class CalendarActionEventSource extends AbstractTestUI { + + private Calendar calendar; + + @Override + protected void setup(VaadinRequest request) { + calendar = new Calendar(new CalendarEventProvider() { + + @Override + public List<com.vaadin.ui.components.calendar.event.CalendarEvent> getEvents( + Date startDate, Date endDate) { + + List<CalendarEvent> events = new ArrayList<CalendarEvent>(); + + CalendarEvent event = null; + try { + event = new BasicEvent("NAME", "TOOLTIP", + new SimpleDateFormat("yyyy-MM-dd hh:mm") + .parse("2013-01-01 07:00"), + new SimpleDateFormat("yyyy-MM-dd hh:mm") + .parse("2013-01-01 11:00")); + } catch (ParseException e) { + // Nothing to do + } + events.add(event); + + return events; + } + + }); + try { + calendar.setStartDate(new SimpleDateFormat("yyyy-MM-dd") + .parse("2013-01-01")); + calendar.setEndDate(new SimpleDateFormat("yyyy-MM-dd") + .parse("2013-01-31")); + } catch (ParseException e) { + // Nothing to do + } + calendar.setImmediate(true); + calendar.setFirstVisibleHourOfDay(6); + calendar.setLastVisibleHourOfDay(22); + calendar.setTimeFormat(TimeFormat.Format24H); + calendar.setHandler((EventResizeHandler) null); + + setEnabled(true); + calendar.addActionHandler(new Handler() { + @Override + public void handleAction(Action action, Object sender, Object target) { + Label label1 = new Label(calendar.toString()); + label1.setId("calendarlabel"); + addComponent(label1); + + Label label2 = new Label(sender.toString()); + label2.setId("senderlabel"); + addComponent(label2); + } + + @Override + public Action[] getActions(Object target, Object sender) { + return new Action[] { new Action("ACTION") }; + } + }); + addComponent(calendar); + calendar.setSizeFull(); + setSizeFull(); + + } + + @Override + protected String getTestDescription() { + return "Calendar action event source should be the calendar itself"; + } + + @Override + protected Integer getTicketNumber() { + return 13191; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/calendar/CalendarActionEventSourceTest.java b/uitest/src/com/vaadin/tests/components/calendar/CalendarActionEventSourceTest.java new file mode 100644 index 0000000000..6fbe77040f --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/calendar/CalendarActionEventSourceTest.java @@ -0,0 +1,83 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * 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. + */ +package com.vaadin.tests.components.calendar; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.tests.tb3.PrivateTB3Configuration; + +/** + * Test that calendar action event source is the calendar, not a private nested + * class in it. + * + * The related code is not browser dependent so only running on a single + * browser. + * + * @author Vaadin Ltd + */ +public class CalendarActionEventSourceTest extends PrivateTB3Configuration { + @Test + public void testActionEventSourceIsCalendarForEmptyCell() throws Exception { + openTestURL(); + + // perform action on empty cell + WebElement element = getDriver().findElement( + By.className("v-calendar-spacer")); + performAction(element); + + checkEventSourceIsCalendar(); + } + + @Test + public void testActionEventSourceIsCalendarForEvent() throws Exception { + openTestURL(); + + // perform action on calendar event + WebElement element = getDriver().findElement( + By.className("v-calendar-event")); + performAction(element); + + checkEventSourceIsCalendar(); + } + + private void performAction(WebElement element) { + // right click + new Actions(getDriver()).contextClick(element).perform(); + WebElement menuItem = getDriver().findElement( + By.className("gwt-MenuItem")); + menuItem.click(); + } + + private void checkEventSourceIsCalendar() { + String calendarObject = getDriver().findElement(By.id("calendarlabel")) + .getText(); + String actionSourceObject = getDriver().findElement( + By.id("senderlabel")).getText(); + Assert.assertEquals( + "Calendar action event source must be the calendar itself", + calendarObject, actionSourceObject); + } + + @Override + protected Class<?> getUIClass() { + return CalendarActionEventSource.class; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/orderedlayout/VerticalLayoutFocusWithDOMChanges.java b/uitest/src/com/vaadin/tests/components/orderedlayout/VerticalLayoutFocusWithDOMChanges.java new file mode 100644 index 0000000000..1e7d817094 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/orderedlayout/VerticalLayoutFocusWithDOMChanges.java @@ -0,0 +1,63 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * 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. + */ +package com.vaadin.tests.components.orderedlayout; + +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.TextField; +import com.vaadin.ui.VerticalLayout; + +public class VerticalLayoutFocusWithDOMChanges extends AbstractTestUI implements + ValueChangeListener { + + Button dummyButton = new Button("Just a button"); + TextField listenedTextField = new TextField(); + TextField changingTextField = new TextField(); + + @Override + protected void setup(VaadinRequest request) { + VerticalLayout content = new VerticalLayout(); + setSizeFull(); + listenedTextField.addValueChangeListener(this); + listenedTextField.setImmediate(true); + changingTextField.setImmediate(true); + content.addComponent(dummyButton); + content.addComponent(listenedTextField); + content.addComponent(changingTextField); + content.setMargin(true); + content.setSpacing(true); + setContent(content); + } + + @Override + protected String getTestDescription() { + return "Check that creating or removing caption wrap doesn't lose focus"; + } + + @Override + protected Integer getTicketNumber() { + return 12967; + } + + @Override + public void valueChange(ValueChangeEvent event) { + changingTextField.setRequired(!changingTextField.isRequired()); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/orderedlayout/VerticalLayoutFocusWithDOMChangesTest.java b/uitest/src/com/vaadin/tests/components/orderedlayout/VerticalLayoutFocusWithDOMChangesTest.java new file mode 100644 index 0000000000..14c26a0e17 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/orderedlayout/VerticalLayoutFocusWithDOMChangesTest.java @@ -0,0 +1,100 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * 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. + */ +package com.vaadin.tests.components.orderedlayout; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.remote.DesiredCapabilities; + +import com.vaadin.testbench.By; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class VerticalLayoutFocusWithDOMChangesTest extends MultiBrowserTest { + + private String initialText = "Some"; + private String incrementalText = " text"; + + @Test + public void inputTextAndChangeFocus() throws InterruptedException { + openTestURL(); + List<WebElement> textFields = getDriver().findElements( + By.tagName("input")); + WebElement tf1 = textFields.get(0); + WebElement tf2 = textFields.get(1); + tf1.sendKeys(initialText); + new Actions(getDriver()).moveToElement(tf2).click().build().perform(); + + WebElement activeElement = getFocusedElement(); + Assert.assertEquals("input", activeElement.getTagName()); + Assert.assertEquals("", activeElement.getAttribute("value")); + + tf1.sendKeys(incrementalText); + new Actions(getDriver()) + .moveToElement( + getDriver().findElement(By.className("v-button"))) + .click().build().perform(); + activeElement = getFocusedElement(); + Assert.assertEquals("Just a button", activeElement.getText()); + + DesiredCapabilities capabilities = getDesiredCapabilities(); + if (capabilities.equals(BrowserUtil.ie(8)) + || capabilities.equals(BrowserUtil.ie(9))) { + // IE8 and IE9 insert cursor in the start of input instead of end. + Assert.assertEquals(incrementalText + initialText, + tf1.getAttribute("value")); + } else { + Assert.assertEquals(initialText + incrementalText, + tf1.getAttribute("value")); + } + } + + @Test + public void moveFocusAndChangeFieldWithValue() { + openTestURL(); + List<WebElement> textFields = getDriver().findElements( + By.tagName("input")); + WebElement tf1 = textFields.get(0); + WebElement tf2 = textFields.get(1); + + String firstText = "This is"; + String secondText = " default value"; + + tf2.sendKeys(firstText); + tf1.sendKeys(initialText); + new Actions(getDriver()).moveToElement(tf2).click().build().perform(); + + WebElement activeElement = getFocusedElement(); + Assert.assertEquals("input", activeElement.getTagName()); + Assert.assertEquals(firstText, activeElement.getAttribute("value")); + + new Actions(getDriver()).sendKeys(secondText).build().perform(); + DesiredCapabilities capabilities = getDesiredCapabilities(); + if (capabilities.equals(BrowserUtil.ie(8)) + || capabilities.equals(BrowserUtil.ie(9))) { + // IE8 and IE9 insert cursor in the start of input instead of end. + Assert.assertEquals(secondText + firstText, + tf2.getAttribute("value")); + } else { + Assert.assertEquals(firstText + secondText, + tf2.getAttribute("value")); + } + } + +} diff --git a/uitest/src/com/vaadin/tests/components/select/SelectItemCaptionRefresh.html b/uitest/src/com/vaadin/tests/components/select/SelectItemCaptionRefresh.html new file mode 100644 index 0000000000..2f8532de61 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/select/SelectItemCaptionRefresh.html @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="" /> +<title>SelectItemCaptionRefresh</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">SelectItemCaptionRefresh</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.components.select.SelectItemCaptionRefresh?restartApplication</td> + <td></td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentsselectSelectItemCaptionRefresh::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VFilterSelect[0]#button</td> + <td>10,14</td> +</tr> +<tr> + <td>mouseClick</td> + <td>//div[@id='VAADIN_COMBOBOX_OPTIONLIST']/div/div[2]/table/tbody/tr[2]/td/span</td> + <td>16,11</td> +</tr> +<tr> + <td>verifyValue</td> + <td>vaadin=runcomvaadintestscomponentsselectSelectItemCaptionRefresh::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VFilterSelect[0]#textbox</td> + <td>start</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsselectSelectItemCaptionRefresh::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VButton[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>verifyValue</td> + <td>vaadin=runcomvaadintestscomponentsselectSelectItemCaptionRefresh::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VFilterSelect[0]#textbox</td> + <td>0</td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/components/select/SelectItemCaptionRefresh.java b/uitest/src/com/vaadin/tests/components/select/SelectItemCaptionRefresh.java new file mode 100644 index 0000000000..de068ed230 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/select/SelectItemCaptionRefresh.java @@ -0,0 +1,75 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * 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. + */ +package com.vaadin.tests.components.select; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Select; + +public class SelectItemCaptionRefresh extends AbstractTestUI { + + final Object itemId = new Object(); + Select select; + + Button.ClickListener clickListener = new Button.ClickListener() { + Integer i = Integer.valueOf(0); + + @Override + public void buttonClick(final ClickEvent event) { + select.setItemCaption(itemId, (i++).toString()); + } + }; + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#setup(com.vaadin.server. + * VaadinRequest) + */ + @Override + protected void setup(VaadinRequest request) { + select = new Select("Foo"); + + select.addItem(itemId); + select.setItemCaption(itemId, "start"); + + addComponent(select); + addComponent(new Button("Update item's caption", clickListener)); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTestDescription() + */ + @Override + protected String getTestDescription() { + return "Selected option should be updated when item caption changes in the Select."; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTicketNumber() + */ + @Override + protected Integer getTicketNumber() { + return 9250; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/ui/TestUIWidgetset.java b/uitest/src/com/vaadin/tests/components/ui/ComponentIncludedInCustomWidgetset.java index e837321b56..f674567a2d 100644 --- a/uitest/src/com/vaadin/tests/components/ui/TestUIWidgetset.java +++ b/uitest/src/com/vaadin/tests/components/ui/ComponentIncludedInCustomWidgetset.java @@ -6,11 +6,13 @@ import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.tests.widgetset.server.MissingFromDefaultWidgetsetComponent; @Widgetset("com.vaadin.tests.widgetset.TestingWidgetSet") -public class TestUIWidgetset extends AbstractTestUI { +public class ComponentIncludedInCustomWidgetset extends AbstractTestUI { @Override protected void setup(VaadinRequest request) { - addComponent(new MissingFromDefaultWidgetsetComponent()); + MissingFromDefaultWidgetsetComponent component = new MissingFromDefaultWidgetsetComponent(); + component.setId("missing-component"); + addComponent(component); } @Override diff --git a/uitest/src/com/vaadin/tests/components/ui/ComponentIncludedInCustomWidgetsetTest.java b/uitest/src/com/vaadin/tests/components/ui/ComponentIncludedInCustomWidgetsetTest.java new file mode 100644 index 0000000000..f27ef5d789 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/ui/ComponentIncludedInCustomWidgetsetTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * 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. + */ +package com.vaadin.tests.components.ui; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Tests if a component is included in a custom widgetset + * (com.vaadin.tests.widgetset.TestingWidgetSet) + * + * @author Vaadin Ltd + */ +public class ComponentIncludedInCustomWidgetsetTest extends MultiBrowserTest { + + @Test + public void testComponentInTestingWidgetsetNotInDefaultWidgetset() { + openTestURL(); + WebElement component = vaadinElementById("missing-component"); + assertEquals( + "This component is available in TestingWidgetset, but not in DefaultWidgetset", + component.getText()); + } +} diff --git a/uitest/src/com/vaadin/tests/components/ui/TestUIWidgetset2.java b/uitest/src/com/vaadin/tests/components/ui/ComponentMissingFromDefaultWidgetset.java index a68cd91a5e..554a461c37 100644 --- a/uitest/src/com/vaadin/tests/components/ui/TestUIWidgetset2.java +++ b/uitest/src/com/vaadin/tests/components/ui/ComponentMissingFromDefaultWidgetset.java @@ -4,11 +4,13 @@ import com.vaadin.server.VaadinRequest; import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.tests.widgetset.server.MissingFromDefaultWidgetsetComponent; -public class TestUIWidgetset2 extends AbstractTestUI { +public class ComponentMissingFromDefaultWidgetset extends AbstractTestUI { @Override protected void setup(VaadinRequest request) { - addComponent(new MissingFromDefaultWidgetsetComponent()); + MissingFromDefaultWidgetsetComponent component = new MissingFromDefaultWidgetsetComponent(); + component.setId("missing-component"); + addComponent(component); } @Override diff --git a/uitest/src/com/vaadin/tests/components/ui/ComponentMissingFromDefaultWidgetsetTest.java b/uitest/src/com/vaadin/tests/components/ui/ComponentMissingFromDefaultWidgetsetTest.java new file mode 100644 index 0000000000..ec8add75e0 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/ui/ComponentMissingFromDefaultWidgetsetTest.java @@ -0,0 +1,42 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * 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. + */ +package com.vaadin.tests.components.ui; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Test for testing if a component is missing from a widgetset. + * + * @author Vaadin Ltd + */ +public class ComponentMissingFromDefaultWidgetsetTest extends MultiBrowserTest { + + @Test + public void testComponentInTestingWidgetset() { + openTestURL(); + WebElement component = vaadinElementById("missing-component"); + assertTrue(component + .getText() + .startsWith( + "Widgetset 'com.vaadin.DefaultWidgetSet' does not contain implementation for com.vaadin.tests.widgetset.server.MissingFromDefaultWidgetsetComponent.")); + + } +} diff --git a/uitest/src/com/vaadin/tests/components/ui/TestUIWidgetset.html b/uitest/src/com/vaadin/tests/components/ui/TestUIWidgetset.html deleted file mode 100644 index 4c10dc4275..0000000000 --- a/uitest/src/com/vaadin/tests/components/ui/TestUIWidgetset.html +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="" /> -<title>Ticket4607</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">Ticket4607</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.components.ui.TestUIWidgetset?restartApplication</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestscomponentsuiTestUIWidgetset::/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[0]</td> - <td>This component is available in TestingWidgetset, but not in DefaultWidgetset</td> -</tr> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.components.ui.TestUIWidgetset2?restartApplication</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestscomponentsuiTestUIWidgetset2::/VVerticalLayout[0]/VVerticalLayout[0]/VUnknownComponent[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td> - <td>Widgetset does not contain implementation for com.vaadin.tests.widgetset.server.MissingFromDefaultWidgetsetComponent. Check its component connector's @Connect mapping, widgetsets GWT module description file and re-compile your widgetset. In case you have downloaded a vaadin add-on package, you might want to refer to add-on instructions.</td> -</tr> -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java index f6fce18fae..55a2b80918 100644 --- a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java +++ b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java @@ -28,9 +28,13 @@ import org.junit.After; import org.junit.Before; import org.junit.runner.RunWith; import org.openqa.selenium.By; +import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.Platform; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.HasInputDevices; +import org.openqa.selenium.interactions.Keyboard; +import org.openqa.selenium.interactions.Mouse; import org.openqa.selenium.remote.BrowserType; import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.remote.RemoteWebDriver; @@ -275,6 +279,21 @@ public abstract class AbstractTB3Test extends TestBenchTestCase { } /** + * Uses JavaScript to determine the currently focused element. + * + * @return Focused element or null + */ + protected WebElement getFocusedElement() { + Object focusedElement = ((JavascriptExecutor) getDriver()) + .executeScript("return document.activeElement"); + if (null != focusedElement) { + return (WebElement) focusedElement; + } else { + return null; + } + } + + /** * Find a Vaadin element based on its id given using Component.setId * * @param id @@ -891,4 +910,22 @@ public abstract class AbstractTB3Test extends TestBenchTestCase { } + /** + * Returns the mouse object for doing mouse commands + * + * @return Returns the mouse + */ + public Mouse getMouse() { + return ((HasInputDevices) getDriver()).getMouse(); + } + + /** + * Returns the keyboard object for controlling keyboard events + * + * @return Return the keyboard + */ + public Keyboard getKeyboard() { + return ((HasInputDevices) getDriver()).getKeyboard(); + } + } |