diff options
78 files changed, 3507 insertions, 1175 deletions
diff --git a/WebContent/VAADIN/themes/tests-valo/_valotest.scss b/WebContent/VAADIN/themes/tests-valo/_valotest.scss index 7c024b323e..568dfec0b8 100644 --- a/WebContent/VAADIN/themes/tests-valo/_valotest.scss +++ b/WebContent/VAADIN/themes/tests-valo/_valotest.scss @@ -141,4 +141,8 @@ .v-accordion-item-color1 .v-accordion-item-caption { @include valo-accordion-item-caption-style($background-color: $color2); } + + .v-menubar-color1 { + @include valo-menubar-style($background-color: $v-selection-color, $unit-size: null); + } } diff --git a/WebContent/VAADIN/themes/valo/components/_button.scss b/WebContent/VAADIN/themes/valo/components/_button.scss index ec74f70eaf..42953ea610 100644 --- a/WebContent/VAADIN/themes/valo/components/_button.scss +++ b/WebContent/VAADIN/themes/valo/components/_button.scss @@ -45,6 +45,10 @@ @include valo-link-style; } + .#{$primary-stylename}-tiny { + @include valo-button-style($unit-size: $v-unit-size--tiny, $bevel: null, $shadow: null, $background-color: null, $font-size: $v-font-size--tiny, $font-weight: null); + } + .#{$primary-stylename}-small { @include valo-button-style($unit-size: $v-unit-size--small, $bevel: null, $shadow: null, $background-color: null, $font-size: $v-font-size--small, $font-weight: null); } @@ -53,6 +57,10 @@ @include valo-button-style($unit-size: $v-unit-size--large, $bevel: null, $shadow: null, $background-color: null, $font-size: $v-font-size--large, $font-weight: null); } + .#{$primary-stylename}-huge { + @include valo-button-style($unit-size: $v-unit-size--huge, $bevel: null, $shadow: null, $background-color: null, $font-size: $v-font-size--huge, $font-weight: null); + } + .#{$primary-stylename}-icon-align-right { @include valo-button-icon-align-right-style; } @@ -65,6 +73,10 @@ width: $v-unit-size; padding: 0; + &.#{$primary-stylename}-tiny { + width: $v-unit-size--tiny; + } + &.#{$primary-stylename}-small { width: $v-unit-size--small; } @@ -73,6 +85,10 @@ width: $v-unit-size--large; } + &.#{$primary-stylename}-huge { + width: $v-unit-size--huge; + } + .#{$primary-stylename}-caption { display: none; } diff --git a/WebContent/VAADIN/themes/valo/components/_combobox.scss b/WebContent/VAADIN/themes/valo/components/_combobox.scss index 4e5cd5bbac..538a5e2694 100644 --- a/WebContent/VAADIN/themes/valo/components/_combobox.scss +++ b/WebContent/VAADIN/themes/valo/components/_combobox.scss @@ -78,6 +78,11 @@ text-align: center; } + .#{$primary-stylename}-tiny { + @include valo-combobox-style($unit-size: $v-unit-size--tiny, $bevel: null, $shadow: null, $gradient: null, $border: null, $border-radius: null, $background-color: null, $states: normal); + font-size: $v-font-size--tiny; + } + .#{$primary-stylename}-small { @include valo-combobox-style($unit-size: $v-unit-size--small, $bevel: null, $shadow: null, $gradient: null, $border: null, $border-radius: null, $background-color: null, $states: normal); font-size: $v-font-size--small; @@ -87,6 +92,11 @@ @include valo-combobox-style($unit-size: $v-unit-size--large, $bevel: null, $shadow: null, $gradient: null, $border: null, $border-radius: null, $background-color: null, $states: normal); font-size: $v-font-size--large; } + + .#{$primary-stylename}-huge { + @include valo-combobox-style($unit-size: $v-unit-size--huge, $bevel: null, $shadow: null, $gradient: null, $border: null, $border-radius: null, $background-color: null, $states: normal); + font-size: $v-font-size--huge; + } } } diff --git a/WebContent/VAADIN/themes/valo/components/_datefield.scss b/WebContent/VAADIN/themes/valo/components/_datefield.scss index 1538681740..8854992032 100644 --- a/WebContent/VAADIN/themes/valo/components/_datefield.scss +++ b/WebContent/VAADIN/themes/valo/components/_datefield.scss @@ -59,6 +59,11 @@ text-align: center; } + .#{$primary-stylename}-tiny { + @include valo-datefield-style($unit-size: $v-unit-size--tiny, $bevel: null, $shadow: null, $border: null, $background-color: null, $states: normal); + font-size: $v-font-size--tiny; + } + .#{$primary-stylename}-small { @include valo-datefield-style($unit-size: $v-unit-size--small, $bevel: null, $shadow: null, $border: null, $background-color: null, $states: normal); font-size: $v-font-size--small; @@ -68,6 +73,11 @@ @include valo-datefield-style($unit-size: $v-unit-size--large, $bevel: null, $shadow: null, $border: null, $background-color: null, $states: normal); font-size: $v-font-size--large; } + + .#{$primary-stylename}-huge { + @include valo-datefield-style($unit-size: $v-unit-size--huge, $bevel: null, $shadow: null, $border: null, $background-color: null, $states: normal); + font-size: $v-font-size--huge; + } } } diff --git a/WebContent/VAADIN/themes/valo/components/_formlayout.scss b/WebContent/VAADIN/themes/valo/components/_formlayout.scss index 25dbfbef28..fc065cec3d 100644 --- a/WebContent/VAADIN/themes/valo/components/_formlayout.scss +++ b/WebContent/VAADIN/themes/valo/components/_formlayout.scss @@ -198,7 +198,6 @@ > .v-label-h3, > .v-label-h4 { border-bottom: none; - color: $v-selection-color; } > .v-label-h3, diff --git a/WebContent/VAADIN/themes/valo/components/_label.scss b/WebContent/VAADIN/themes/valo/components/_label.scss index 29d811fc9a..e61aa4ec11 100644 --- a/WebContent/VAADIN/themes/valo/components/_label.scss +++ b/WebContent/VAADIN/themes/valo/components/_label.scss @@ -1,6 +1,7 @@ $v-font-weight--header: $v-font-weight - 100 !default; $v-line-height--header: 1.1 !default; $v-font-family--header: null !default; +$v-font-color--colored: $v-selection-color !default; $v-font-size--h1: 2.4em !default; $v-font-size--h2: 1.6em !default; @@ -104,6 +105,10 @@ $v-letter-spacing--h4: 0 !default; @if $include-additional-styles { + .#{$primary-stylename}-colored { + color: $v-font-color--colored; + } + .#{$primary-stylename}-large { font-size: $v-font-size--large; } @@ -112,6 +117,14 @@ $v-letter-spacing--h4: 0 !default; font-size: $v-font-size--small; } + .#{$primary-stylename}-tiny { + font-size: $v-font-size--tiny; + } + + .#{$primary-stylename}-huge { + font-size: $v-font-size--huge; + } + .#{$primary-stylename}-bold { font-weight: $v-font-weight + 200; } diff --git a/WebContent/VAADIN/themes/valo/components/_menubar.scss b/WebContent/VAADIN/themes/valo/components/_menubar.scss index e79e6898a9..f03bc3d022 100644 --- a/WebContent/VAADIN/themes/valo/components/_menubar.scss +++ b/WebContent/VAADIN/themes/valo/components/_menubar.scss @@ -1,24 +1,8 @@ @mixin valo-menubar ($primary-stylename: v-menubar, $include-additional-styles: contains($v-included-additional-styles, menubar)) { .#{$primary-stylename} { - @include valo-button-static-style($states: normal, $vertical-centering: false); - @include valo-button-style($states: normal, $cursor: default); - padding: 0; - text-align: left; - overflow: hidden; - - &:focus:not(.v-disabled) { - @include valo-button-focus-style($border-fallback: none, $include-box-shadow: false); - $box-shadow: valo-bevel-and-shadow($bevel: $v-bevel, $shadow: $v-shadow, $gradient: $v-gradient); - @if type-of($v-focus-style) == list { - $box-shadow: $box-shadow, $v-focus-style; - } - @include box-shadow($box-shadow); - } - - &.v-disabled { - @include opacity($v-disabled-opacity); - } + @include valo-button-static-style($states: normal focus disabled, $vertical-centering: false); + @include valo-menubar-style; } .#{$primary-stylename}:active:after { @@ -60,6 +44,20 @@ .#{$primary-stylename} .#{$primary-stylename}-submenu-indicator { display: none; + + + .#{$primary-stylename}-menuitem-caption:after { + font-family: FontAwesome; + content: "\f078"; + font-size: 0.7em; + vertical-align: .15em; + margin: 0 -.2em 0 .5em; + // IE filters are not supported on pseudo elements + opacity: .5; + } + + + .#{$primary-stylename}-menuitem-caption:empty:after { + margin-left: -.2em; + } } .#{$primary-stylename}-popup { @@ -70,10 +68,10 @@ } } - + @if $include-additional-styles { .#{$primary-stylename}-small { - @include valo-menubar-small-style($unit-size: $v-unit-size--small); + @include valo-menubar-style($background-color: null, $unit-size: $v-unit-size--small); font-size: $v-font-size--small; } @@ -87,6 +85,27 @@ +@mixin valo-menubar-style ($primary-stylename: v-menubar, $background-color: $v-background-color, $unit-size: $v-unit-size) { + @include valo-button-style($states: normal focus, $cursor: default, $background-color: $background-color, $unit-size: $unit-size); + padding: 0; + text-align: left; + + @if $unit-size { + line-height: $unit-size - first-number($v-border) * 2 - 1px; + + > .#{$primary-stylename}-menuitem { + padding: 0 round($unit-size/2.6); + + &[class*="-icon-only"] { + width: $unit-size; + } + } + } +} + + + + @mixin valo-menubar-menuitem-style { $border-width: first-number($v-border); position: relative; @@ -95,31 +114,37 @@ @include box-sizing(border-box); @include valo-button-style($states: normal, $border-radius: 0, $shadow: null, $font-color: inherit, $cursor: pointer); background: transparent; + @include box-shadow(none); border-width: 0 $border-width 0 0; + border-color: inherit; height: 100%; + line-height: inherit; vertical-align: top; - line-height: $v-unit-size - $border-width*2 - 1px; text-align: center; @if $border-width == 0 { margin-right: 1px; } - $br: $v-border-radius - $border-width - 1px; + $br: max(0, $v-border-radius - $border-width); &:first-child { border-left-width: 0; - border-radius: $br 0 0 $br; + @if $v-border-radius > 0 { + border-radius: $br 0 0 $br; + } } &:last-child { - border-radius: 0 $br $br 0; - margin-right: -$border-width; + @if $v-border-radius > 0 { + border-radius: 0 $br $br 0; + } + border-right-width: 0; } &:first-child:last-child { - border-radius: $br; - border-right-width: 0; - margin-right: 0; + @if $v-border-radius > 0 { + border-radius: $br; + } } &:before { @@ -253,20 +278,6 @@ } - -@mixin valo-menubar-small-style ($primary-stylename: v-menubar, $unit-size: round($v-unit-size * 0.8)) { - height: $unit-size; - - .#{$primary-stylename}-menuitem { - line-height: $unit-size - first-number($v-border)*2; - padding: 0 round($unit-size/2.5); - - &[class*="-icon-only"] { - width: $unit-size; - } - } -} - @mixin valo-menubar-borderless-style ($primary-stylename: v-menubar) { border: none; border-radius: 0; @@ -275,9 +286,8 @@ background: transparent; color: inherit; - &:not(.v-disabled):focus { - border: none; - @include box-shadow(none); + &:focus:after { + display: none; } .#{$primary-stylename}-menuitem { @@ -294,7 +304,8 @@ } &:first-child, - &:last-child { + &:last-child, + &:first-child:last-child { border-radius: $v-border-radius; } diff --git a/WebContent/VAADIN/themes/valo/components/_textarea.scss b/WebContent/VAADIN/themes/valo/components/_textarea.scss index 4c5d99b8e2..5e524bfb9e 100644 --- a/WebContent/VAADIN/themes/valo/components/_textarea.scss +++ b/WebContent/VAADIN/themes/valo/components/_textarea.scss @@ -19,6 +19,11 @@ @include valo-textfield-borderless-style; } + .#{$primary-stylename}-tiny { + @include valo-textarea-style($unit-size: $v-unit-size--tiny, $states: normal, $background-color: null, $border: null, $bevel: null, $shadow: null); + font-size: $v-font-size--tiny; + } + .#{$primary-stylename}-small { @include valo-textarea-style($unit-size: $v-unit-size--small, $states: normal, $background-color: null, $border: null, $bevel: null, $shadow: null); font-size: $v-font-size--small; @@ -29,6 +34,11 @@ font-size: $v-font-size--large; } + .#{$primary-stylename}-huge { + @include valo-textarea-style($unit-size: $v-unit-size--huge, $states: normal, $background-color: null, $border: null, $bevel: null, $shadow: null); + font-size: $v-font-size--huge; + } + .#{$primary-stylename}-align-right { text-align: right; } diff --git a/WebContent/VAADIN/themes/valo/components/_textfield.scss b/WebContent/VAADIN/themes/valo/components/_textfield.scss index 75cfc5ef85..0b4fa50fb2 100644 --- a/WebContent/VAADIN/themes/valo/components/_textfield.scss +++ b/WebContent/VAADIN/themes/valo/components/_textfield.scss @@ -1,5 +1,5 @@ $v-textfield-background-color: if(is-dark-color($v-app-background-color), darken($v-app-background-color, 4%), lighten($v-app-background-color, 8%)) !default; -$v-textfield-background-color--readonly: $v-app-background-color; +$v-textfield-background-color--readonly: darkest-color($v-app-background-color, darken($v-textfield-background-color, 2%)); $v-textfield-bevel: inset 0 1px 0 v-shade !default; $v-textfield-shadow: 0 1px 0 (v-tint 2) !default; $v-textfield-font-weight: 400 !default; @@ -30,6 +30,11 @@ $v-textfield-disabled-opacity: $v-disabled-opacity !default; @include valo-textfield-borderless-style; } + .#{$primary-stylename}-tiny { + @include valo-textfield-style($unit-size: $v-unit-size--tiny, $states: normal, $background-color: null, $border: null, $gradient: null, $bevel: null, $shadow: null); + font-size: $v-font-size--tiny; + } + .#{$primary-stylename}-small { @include valo-textfield-style($unit-size: $v-unit-size--small, $states: normal, $background-color: null, $border: null, $gradient: null, $bevel: null, $shadow: null); font-size: $v-font-size--small; @@ -40,9 +45,16 @@ $v-textfield-disabled-opacity: $v-disabled-opacity !default; font-size: $v-font-size--large; } + .#{$primary-stylename}-huge { + @include valo-textfield-style($unit-size: $v-unit-size--huge, $states: normal, $background-color: null, $border: null, $gradient: null, $bevel: null, $shadow: null); + font-size: $v-font-size--huge; + } + @include valo-textfield-inline-icon($stylenames: inline-icon); + @include valo-textfield-inline-icon($stylenames: inline-icon tiny, $unit-size: $v-unit-size--tiny, $font-size: $v-font-size--tiny); @include valo-textfield-inline-icon($stylenames: inline-icon small, $unit-size: $v-unit-size--small, $font-size: $v-font-size--small); @include valo-textfield-inline-icon($stylenames: inline-icon large, $unit-size: $v-unit-size--large, $font-size: $v-font-size--large); + @include valo-textfield-inline-icon($stylenames: inline-icon huge, $unit-size: $v-unit-size--huge, $font-size: $v-font-size--huge); .#{$primary-stylename}-align-right { text-align: right; diff --git a/WebContent/VAADIN/themes/valo/components/_tree.scss b/WebContent/VAADIN/themes/valo/components/_tree.scss index 7e00f4ec09..93553fe55a 100644 --- a/WebContent/VAADIN/themes/valo/components/_tree.scss +++ b/WebContent/VAADIN/themes/valo/components/_tree.scss @@ -218,7 +218,8 @@ $v-tree-expand-animation-enabled: false !default; // Drag'n'drop styles .#{$primary-stylename}-node-drag-top:before, - .#{$primary-stylename}-node-drag-bottom:after { + .#{$primary-stylename}-node-drag-bottom:after, + .#{$primary-stylename}-node-drag-bottom.#{$primary-stylename}-node-dragfolder.#{$primary-stylename}-node-expanded > .#{$primary-stylename}-node-children:before { content: "\2022"; display: block; position: absolute; @@ -230,6 +231,12 @@ $v-tree-expand-animation-enabled: false !default; color: $v-focus-color; text-indent: round($v-font-size/-4); text-shadow: 0 0 1px $v-background-color, 0 0 1px $v-background-color; + opacity: 1; + visibility: visible; + } + + .#{$primary-stylename}-node-drag-bottom.#{$primary-stylename}-node-dragfolder.#{$primary-stylename}-node-expanded:after { + content: none; } .#{$primary-stylename}-node-caption-drag-center { diff --git a/WebContent/VAADIN/themes/valo/components/_window.scss b/WebContent/VAADIN/themes/valo/components/_window.scss index d866ce2584..97859a62b2 100644 --- a/WebContent/VAADIN/themes/valo/components/_window.scss +++ b/WebContent/VAADIN/themes/valo/components/_window.scss @@ -125,7 +125,6 @@ $v-window-modality-curtain-background-color: #222 !default; line-height: $v-unit-size - 3px; text-align: center; cursor: pointer; - font-family: FontAwesome; font-size: round($v-font-size * 1.3); color: valo-font-color($v-window-background-color, .4); diff --git a/WebContent/VAADIN/themes/valo/shared/_variables.scss b/WebContent/VAADIN/themes/valo/shared/_variables.scss index b1c113b2cc..7dd3827298 100644 --- a/WebContent/VAADIN/themes/valo/shared/_variables.scss +++ b/WebContent/VAADIN/themes/valo/shared/_variables.scss @@ -60,14 +60,20 @@ $v-required-field-indicator-color : $v-error-indicator-color $v-friendly-color : #2c9720 !default; -$v-scaling-factor--small : 0.8 !default; +$v-scaling-factor--tiny : 0.75 !default; +$v-scaling-factor--small : 0.85 !default; $v-scaling-factor--large : 1.2 !default; +$v-scaling-factor--huge : 1.6 !default; +$v-unit-size--tiny : round($v-unit-size * $v-scaling-factor--tiny) !default; $v-unit-size--small : round($v-unit-size * $v-scaling-factor--small) !default; $v-unit-size--large : round($v-unit-size * $v-scaling-factor--large) !default; +$v-unit-size--huge : round($v-unit-size * $v-scaling-factor--huge) !default; -$v-font-size--small : round($v-font-size * $v-scaling-factor--small) !default; -$v-font-size--large : round($v-font-size * $v-scaling-factor--large) !default; +$v-font-size--tiny : ceil($v-font-size * $v-scaling-factor--tiny) !default; +$v-font-size--small : ceil($v-font-size * $v-scaling-factor--small) !default; +$v-font-size--large : ceil($v-font-size * $v-scaling-factor--large) !default; +$v-font-size--huge : ceil($v-font-size * $v-scaling-factor--huge) !default; diff --git a/WebContent/html-tests/ComponentFocus.html b/WebContent/html-tests/ComponentFocus.html new file mode 100644 index 0000000000..0a822520e0 --- /dev/null +++ b/WebContent/html-tests/ComponentFocus.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="UTF-8"> +<title>Insert title here</title> + +<script type="text/javascript"> + +</script> + +</head> +<body> +<button onfocus="console.log('button focus');" onblur="console.log('button blur');">Focus me</button> +<textarea onfocus="console.log('textarea focus');" onblur="console.log('textarea blur');">Focus me too</textarea> +</body> +</html>
\ No newline at end of file diff --git a/build.properties b/build.properties index 488c2fa32f..0a25dab4b9 100644 --- a/build.properties +++ b/build.properties @@ -6,5 +6,5 @@ vaadin.url=http://vaadin.com vaadin.java.version=1.6 vaadin.version=0.0.0.unversioned-development-build vaadin.sass.version=0.9.9 -gwt.version=2.6.0.vaadin3 +gwt.version=2.6.0.vaadin5 commons-io.version=2.4 diff --git a/build/ide.xml b/build/ide.xml index fa8b85ee23..c7183077a9 100755 --- a/build/ide.xml +++ b/build/ide.xml @@ -71,6 +71,27 @@ <antcall target="compile-theme" inheritRefs="true"> <param name="theme" value="valo" /> </antcall> + <antcall target="compile-theme" inheritRefs="true"> + <param name="theme" value="tests-valo" /> + </antcall> + <antcall target="compile-theme" inheritRefs="true"> + <param name="theme" value="tests-valo-dark" /> + </antcall> + <antcall target="compile-theme" inheritRefs="true"> + <param name="theme" value="tests-valo-metro" /> + </antcall> + <antcall target="compile-theme" inheritRefs="true"> + <param name="theme" value="tests-valo-flat" /> + </antcall> + <antcall target="compile-theme" inheritRefs="true"> + <param name="theme" value="tests-valo-flatdark" /> + </antcall> + <antcall target="compile-theme" inheritRefs="true"> + <param name="theme" value="tests-valo-facebook" /> + </antcall> + <antcall target="compile-theme" inheritRefs="true"> + <param name="theme" value="tests-valo-blueprint" /> + </antcall> </parallel> </target> diff --git a/buildhelpers/ivy.xml b/buildhelpers/ivy.xml index 9117721444..cf04bfdc5d 100644 --- a/buildhelpers/ivy.xml +++ b/buildhelpers/ivy.xml @@ -18,7 +18,6 @@ <conf name="build" /> <conf name="build-provided" /> <conf name="ide" visibility="private" /> - <conf name="test" /> </configurations> <publications> <artifact type="jar" /> diff --git a/client-compiler/src/com/vaadin/tools/CvalChecker.java b/client-compiler/src/com/vaadin/tools/CvalChecker.java index 2de7e10faa..e426c5c4e6 100644 --- a/client-compiler/src/com/vaadin/tools/CvalChecker.java +++ b/client-compiler/src/com/vaadin/tools/CvalChecker.java @@ -26,6 +26,7 @@ import java.net.URLConnection; import java.text.MessageFormat; import java.util.Arrays; import java.util.Date; +import java.util.List; import java.util.Locale; import java.util.ResourceBundle; import java.util.prefs.Preferences; @@ -465,7 +466,8 @@ public final class CvalChecker { if (url != null) { try { - key = IOUtils.toString(url.openStream()); + key = readKeyFromFile(url, + computeMajorVersion(productVersion)); if (key != null && !(key = key.trim()).isEmpty()) { return key; } @@ -480,6 +482,22 @@ public final class CvalChecker { productTitle, null, null); } + String readKeyFromFile(URL url, int majorVersion) throws IOException { + String majorVersionStr = String.valueOf(majorVersion); + List<String> lines = IOUtils.readLines(url.openStream()); + String defaultKey = null; + for (String line : lines) { + String[] parts = line.split("\\s*=\\s*"); + if (parts.length < 2) { + defaultKey = parts[0].trim(); + } + if (parts[0].equals(majorVersionStr)) { + return parts[1].trim(); + } + } + return defaultKey; + } + static String getErrorMessage(String key, Object... pars) { Locale loc = Locale.getDefault(); ResourceBundle res = ResourceBundle.getBundle( diff --git a/client-compiler/tests/src/com/vaadin/tools/CvalCheckerTest.java b/client-compiler/tests/src/com/vaadin/tools/CvalCheckerTest.java index 51b12f4c7e..2985f61631 100644 --- a/client-compiler/tests/src/com/vaadin/tools/CvalCheckerTest.java +++ b/client-compiler/tests/src/com/vaadin/tools/CvalCheckerTest.java @@ -24,13 +24,17 @@ import static com.vaadin.tools.CvalChecker.GRACE_DAYS_MSECS; import static com.vaadin.tools.CvalChecker.cacheLicenseInfo; import static com.vaadin.tools.CvalChecker.deleteCache; import static com.vaadin.tools.CvalChecker.parseJson; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileDescriptor; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; +import java.io.PrintWriter; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; @@ -147,7 +151,7 @@ public class CvalCheckerTest { productTitleCval); Assert.fail(); } catch (InvalidCvalException expected) { - Assert.assertEquals(productNameCval, expected.name); + assertEquals(productNameCval, expected.name); } Assert.assertFalse(cacheExists(productNameCval)); @@ -158,7 +162,7 @@ public class CvalCheckerTest { productTitleCval); Assert.fail(); } catch (InvalidCvalException expected) { - Assert.assertEquals(productNameCval, expected.name); + assertEquals(productNameCval, expected.name); } Assert.assertFalse(cacheExists(productNameCval)); @@ -169,7 +173,7 @@ public class CvalCheckerTest { productTitleCval); Assert.fail(); } catch (InvalidCvalException expected) { - Assert.assertEquals(productNameCval, expected.name); + assertEquals(productNameCval, expected.name); } Assert.assertFalse(cacheExists(productNameCval)); @@ -180,7 +184,7 @@ public class CvalCheckerTest { productTitleCval); Assert.fail(); } catch (InvalidCvalException expected) { - Assert.assertEquals(productNameCval, expected.name); + assertEquals(productNameCval, expected.name); } Assert.assertFalse(cacheExists(productNameCval)); @@ -207,7 +211,7 @@ public class CvalCheckerTest { } catch (InvalidCvalException expected) { Assert.fail(); } catch (UnreachableCvalServerException expected) { - Assert.assertEquals(productNameCval, expected.name); + assertEquals(productNameCval, expected.name); } Assert.assertFalse(cacheExists(productNameCval)); @@ -221,7 +225,7 @@ public class CvalCheckerTest { } catch (InvalidCvalException expected) { Assert.fail(); } catch (UnreachableCvalServerException expected) { - Assert.assertEquals(productNameCval, expected.name); + assertEquals(productNameCval, expected.name); } Assert.assertFalse(cacheExists(productNameCval)); @@ -234,7 +238,7 @@ public class CvalCheckerTest { productTitleCval); Assert.fail(); } catch (InvalidCvalException expected) { - Assert.assertEquals(productNameCval, expected.name); + assertEquals(productNameCval, expected.name); // Check that we use server customized message if it comes Assert.assertTrue(expected.getMessage().contains("Custom")); } @@ -255,7 +259,7 @@ public class CvalCheckerTest { productTitleCval); Assert.fail(); } catch (InvalidCvalException expected) { - Assert.assertEquals(productNameCval, expected.name); + assertEquals(productNameCval, expected.name); } Assert.assertTrue(cacheExists(productNameCval)); } @@ -339,4 +343,131 @@ public class CvalCheckerTest { static void restoreSystemOut() { System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out))); } + + @Test(expected = FileNotFoundException.class) + public void testReadKeyFromFile_NonexistingLicenseFile() throws Exception { + licenseChecker.readKeyFromFile(new URL("file:///foobar.baz"), 4); + } + + @Test + public void testReadKeyFromFile_LicenseFileEmpty() throws Exception { + File tmpLicenseFile = File.createTempFile("license", "lic"); + + assertNull(licenseChecker.readKeyFromFile(tmpLicenseFile.toURI() + .toURL(), 4)); + + tmpLicenseFile.delete(); + } + + @Test + public void testReadKeyFromFile_LicenseFileHasSingleUnidentifiedKey() + throws Exception { + File tmpLicenseFile = File.createTempFile("license", "lic"); + PrintWriter out = new PrintWriter(tmpLicenseFile); + out.println("this-is-a-license"); + out.close(); + + assertEquals("this-is-a-license", licenseChecker.readKeyFromFile( + tmpLicenseFile.toURI().toURL(), 4)); + + tmpLicenseFile.delete(); + } + + @Test + public void testReadKeyFromFile_LicenseFileHasSingleIdentifiedKey() + throws Exception { + File tmpLicenseFile = File.createTempFile("license", "lic"); + PrintWriter out = new PrintWriter(tmpLicenseFile); + out.println("4=this-is-a-license"); + out.close(); + + assertEquals("this-is-a-license", licenseChecker.readKeyFromFile( + tmpLicenseFile.toURI().toURL(), 4)); + + tmpLicenseFile.delete(); + } + + @Test + public void testReadKeyFromFile_LicenseFileHasMultipleKeys() + throws Exception { + File tmpLicenseFile = File.createTempFile("license", "lic"); + PrintWriter out = new PrintWriter(tmpLicenseFile); + out.println("4=this-is-a-license"); + out.println("5=this-is-another-license"); + out.close(); + + assertEquals("this-is-a-license", licenseChecker.readKeyFromFile( + tmpLicenseFile.toURI().toURL(), 4)); + assertEquals("this-is-another-license", licenseChecker.readKeyFromFile( + tmpLicenseFile.toURI().toURL(), 5)); + + tmpLicenseFile.delete(); + } + + @Test + public void testReadKeyFromFile_LicenseFileHasMultipleKeysWithWhitespace() + throws Exception { + File tmpLicenseFile = File.createTempFile("license", "lic"); + PrintWriter out = new PrintWriter(tmpLicenseFile); + out.println("4 = this-is-a-license"); + out.println("5 = this-is-another-license"); + out.close(); + + assertEquals("this-is-a-license", licenseChecker.readKeyFromFile( + tmpLicenseFile.toURI().toURL(), 4)); + assertEquals("this-is-another-license", licenseChecker.readKeyFromFile( + tmpLicenseFile.toURI().toURL(), 5)); + + tmpLicenseFile.delete(); + } + + @Test + public void testReadKeyFromFile_RequestedVersionMissing() throws Exception { + File tmpLicenseFile = File.createTempFile("license", "lic"); + PrintWriter out = new PrintWriter(tmpLicenseFile); + out.println("4 = this-is-a-license"); + out.println("5 = this-is-another-license"); + out.close(); + + assertNull(licenseChecker.readKeyFromFile(tmpLicenseFile.toURI() + .toURL(), 3)); + + tmpLicenseFile.delete(); + } + + @Test + public void testReadKeyFromFile_FallbackToDefaultKey() throws Exception { + File tmpLicenseFile = File.createTempFile("license", "lic"); + PrintWriter out = new PrintWriter(tmpLicenseFile); + out.println("this-is-a-license"); + out.println("5 = this-is-another-license"); + out.close(); + + assertEquals("this-is-a-license", licenseChecker.readKeyFromFile(tmpLicenseFile.toURI() + .toURL(), 3)); + assertEquals("this-is-a-license", licenseChecker.readKeyFromFile(tmpLicenseFile.toURI() + .toURL(), 4)); + assertEquals("this-is-another-license", licenseChecker.readKeyFromFile( + tmpLicenseFile.toURI().toURL(), 5)); + + tmpLicenseFile.delete(); + } + + @Test + public void testReadKeyFromFile_FallbackToDefaultKeyReversed() throws Exception { + File tmpLicenseFile = File.createTempFile("license", "lic"); + PrintWriter out = new PrintWriter(tmpLicenseFile); + out.println("5 = this-is-another-license"); + out.println("this-is-a-license"); + out.close(); + + assertEquals("this-is-a-license", licenseChecker.readKeyFromFile(tmpLicenseFile.toURI() + .toURL(), 3)); + assertEquals("this-is-a-license", licenseChecker.readKeyFromFile(tmpLicenseFile.toURI() + .toURL(), 4)); + assertEquals("this-is-another-license", licenseChecker.readKeyFromFile( + tmpLicenseFile.toURI().toURL(), 5)); + + tmpLicenseFile.delete(); + } } diff --git a/client/src/com/vaadin/DefaultWidgetSet.gwt.xml b/client/src/com/vaadin/DefaultWidgetSet.gwt.xml index 2719493853..8512d547e3 100755 --- a/client/src/com/vaadin/DefaultWidgetSet.gwt.xml +++ b/client/src/com/vaadin/DefaultWidgetSet.gwt.xml @@ -14,4 +14,5 @@ file. Speeds up compilation and does not make the Javascript significantly larger. --> <collapse-all-properties /> + </module> diff --git a/client/src/com/vaadin/Vaadin.gwt.xml b/client/src/com/vaadin/Vaadin.gwt.xml index 711729f64f..aad0563975 100644 --- a/client/src/com/vaadin/Vaadin.gwt.xml +++ b/client/src/com/vaadin/Vaadin.gwt.xml @@ -68,7 +68,7 @@ <property-provider name="modernie"><![CDATA[ { var ua = $wnd.navigator.userAgent; - if (ua.indexOf('IE') == -1 && ua.indexOf('Trident') != -1) { return 'yes'; } + if (ua.indexOf('MSIE') == -1 && ua.indexOf('Trident') != -1) { return 'yes'; } return 'none'; } ]]></property-provider> diff --git a/client/src/com/vaadin/client/Util.java b/client/src/com/vaadin/client/Util.java index 49c862006b..e37b044826 100644 --- a/client/src/com/vaadin/client/Util.java +++ b/client/src/com/vaadin/client/Util.java @@ -1420,6 +1420,37 @@ public class Util { } /** + * Sets the selection range of an input element. + * + * We need this JSNI function to set selection range so that we can use the + * optional direction attribute to set the anchor to the end and the focus + * to the start. This makes Firefox work the same way as other browsers + * (#13477) + * + * @param elem + * the html input element. + * @param pos + * the index of the first selected character. + * @param length + * the selection length. + * @param direction + * a string indicating the direction in which the selection was + * performed. This may be "forward" or "backward", or "none" if + * the direction is unknown or irrelevant. + * + * @since + */ + public native static void setSelectionRange(Element elem, int pos, + int length, String direction) + /*-{ + try { + elem.setSelectionRange(pos, pos + length, direction); + } catch (e) { + // Firefox throws exception if TextBox is not visible, even if attached + } + }-*/; + + /** * Wrap a css size value and its unit and translate back and forth to the * string representation.<br/> * Eg. 50%, 123px, ... @@ -1571,7 +1602,8 @@ public class Util { * @return true if the two sizes are equals, otherwise false. */ public static boolean equals(String cssSize1, String cssSize2) { - return CssSize.fromString(cssSize1).equals(CssSize.fromString(cssSize2)); + return CssSize.fromString(cssSize1).equals( + CssSize.fromString(cssSize2)); } } diff --git a/client/src/com/vaadin/client/ui/VDragAndDropWrapper.java b/client/src/com/vaadin/client/ui/VDragAndDropWrapper.java index 4010ffd542..7bf341a387 100644 --- a/client/src/com/vaadin/client/ui/VDragAndDropWrapper.java +++ b/client/src/com/vaadin/client/ui/VDragAndDropWrapper.java @@ -114,7 +114,8 @@ public class VDragAndDropWrapper extends VCustomComponent implements * @return true if the event was handled as a drag start event */ private boolean startDrag(NativeEvent event) { - if (dragStartMode == WRAPPER || dragStartMode == COMPONENT) { + if (dragStartMode == WRAPPER || dragStartMode == COMPONENT + || dragStartMode == COMPONENT_OTHER) { VTransferable transferable = new VTransferable(); transferable.setDragSource(getConnector()); @@ -130,6 +131,10 @@ public class VDragAndDropWrapper extends VCustomComponent implements if (dragStartMode == WRAPPER) { dragEvent.createDragImage(getElement(), true); + } else if (dragStartMode == COMPONENT_OTHER + && getDragImageWidget() != null) { + dragEvent.createDragImage(getDragImageWidget().getElement(), + true); } else { dragEvent.createDragImage(widget.getElement(), true); } @@ -142,6 +147,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements protected final static int COMPONENT = 1; protected final static int WRAPPER = 2; protected final static int HTML5 = 3; + protected final static int COMPONENT_OTHER = 4; /** For internal use only. May be removed or replaced in the future. */ public int dragStartMode; @@ -458,6 +464,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements * Flag used by html5 dd */ private boolean currentlyValid; + private Widget dragImageWidget; private static final String OVER_STYLE = "v-ddwrapper-over"; @@ -661,4 +668,22 @@ public class VDragAndDropWrapper extends VCustomComponent implements notifySizePotentiallyChanged(); } + /** + * Set the widget that will be used as the drag image when using + * DragStartMode {@link COMPONENT_OTHER} . + * + * @param widget + */ + public void setDragAndDropWidget(Widget widget) { + dragImageWidget = widget; + } + + /** + * @return the widget used as drag image. Returns <code>null</code> if no + * widget is set. + */ + public Widget getDragImageWidget() { + return dragImageWidget; + } + } diff --git a/client/src/com/vaadin/client/ui/VFilterSelect.java b/client/src/com/vaadin/client/ui/VFilterSelect.java index 6ba0785acc..230c9e6639 100644 --- a/client/src/com/vaadin/client/ui/VFilterSelect.java +++ b/client/src/com/vaadin/client/ui/VFilterSelect.java @@ -254,7 +254,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, /** * Shows the popup where the user can see the filtered options - * + * * @param currentSuggestions * The filtered suggestions * @param currentPage @@ -345,7 +345,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, /** * Should the next page button be visible to the user? - * + * * @param active */ private void setNextButtonActive(boolean active) { @@ -365,7 +365,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, /** * Should the previous page button be visible to the user - * + * * @param active */ private void setPrevButtonActive(boolean active) { @@ -554,7 +554,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * amount of items are visible at a time and a scrollbar or buttons are * visible to change page. If paging is turned of then all options are * rendered into the popup menu. - * + * * @param paging * Should the paging be turned on? */ @@ -679,7 +679,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, /** * Was the popup just closed? - * + * * @return true if popup was just closed */ public boolean isJustClosed() { @@ -708,7 +708,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, /** * Updates style names in suggestion popup to help theme building. - * + * * @param uidl * UIDL for the whole combo box * @param componentState @@ -799,7 +799,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, /** * Sets the suggestions rendered in the menu - * + * * @param suggestions * The suggestions to be rendered in the menu */ @@ -1057,11 +1057,33 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, @Override public void setSelectionRange(int pos, int length) { if (textInputEnabled) { - super.setSelectionRange(pos, length); + /* + * set selection range with a backwards direction: anchor at the + * back, focus at the front. This means that items that are too + * long to display will display from the start and not the end + * even on Firefox. + * + * We need the JSNI function to set selection range so that we + * can use the optional direction attribute to set the anchor to + * the end and the focus to the start. This makes Firefox work + * the same way as other browsers (#13477) + */ + Util.setSelectionRange(getElement(), pos, length, "backward"); + } else { - super.setSelectionRange(0, getValue().length()); + /* + * Setting the selectionrange for an uneditable textbox leads to + * unwanted behaviour when the width of the textbox is narrower + * than the width of the entry: the end of the entry is shown + * instead of the beginning. (see #13477) + * + * To avoid this, we set the caret to the beginning of the line. + */ + + super.setSelectionRange(0, 0); } } + } @Deprecated @@ -1456,9 +1478,8 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, private void setText(final String text) { /** - * To leave caret in the beginning of the line. - * SetSelectionRange wouldn't work on IE - * (see #13477) + * To leave caret in the beginning of the line. SetSelectionRange + * wouldn't work on IE (see #13477) */ Direction previousDirection = tb.getDirection(); tb.setDirection(Direction.RTL); @@ -1763,10 +1784,14 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, if (!allowNewItem) { /* * New items are not allowed: If there is only one - * suggestion, select that. Otherwise do nothing. + * suggestion, select that. If there is more than one + * suggestion Enter key should work as Escape key. Otherwise + * do nothing. */ if (currentSuggestions.size() == 1) { onSuggestionSelected(currentSuggestions.get(0)); + } else if (currentSuggestions.size() > 1) { + reset(); } } else { // Handle addition of new items. diff --git a/client/src/com/vaadin/client/ui/VTabsheet.java b/client/src/com/vaadin/client/ui/VTabsheet.java index 15d9c83c49..aff1848647 100644 --- a/client/src/com/vaadin/client/ui/VTabsheet.java +++ b/client/src/com/vaadin/client/ui/VTabsheet.java @@ -1,12 +1,12 @@ /* * Copyright 2000-2014 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 @@ -42,9 +42,12 @@ import com.google.gwt.event.dom.client.FocusHandler; import com.google.gwt.event.dom.client.HasBlurHandlers; import com.google.gwt.event.dom.client.HasFocusHandlers; import com.google.gwt.event.dom.client.HasKeyDownHandlers; +import com.google.gwt.event.dom.client.HasMouseDownHandlers; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyDownEvent; import com.google.gwt.event.dom.client.KeyDownHandler; +import com.google.gwt.event.dom.client.MouseDownEvent; +import com.google.gwt.event.dom.client.MouseDownHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.regexp.shared.MatchResult; import com.google.gwt.regexp.shared.RegExp; @@ -74,7 +77,9 @@ import com.vaadin.shared.ui.tabsheet.TabsheetServerRpc; import com.vaadin.shared.ui.tabsheet.TabsheetState; public class VTabsheet extends VTabsheetBase implements Focusable, - FocusHandler, BlurHandler, KeyDownHandler, SubPartAware { + SubPartAware, + // TODO: These listeners are due to be removed in 7.3 + FocusHandler, BlurHandler, KeyDownHandler { private static class VCloseEvent { private Tab tab; @@ -95,10 +100,10 @@ public class VTabsheet extends VTabsheetBase implements Focusable, /** * Representation of a single "tab" shown in the TabBar - * + * */ public static class Tab extends SimplePanel implements HasFocusHandlers, - HasBlurHandlers, HasKeyDownHandlers { + HasBlurHandlers, HasMouseDownHandlers, HasKeyDownHandlers { private static final String TD_CLASSNAME = CLASSNAME + "-tabitemcell"; private static final String TD_FIRST_CLASSNAME = TD_CLASSNAME + "-first"; @@ -152,10 +157,6 @@ public class VTabsheet extends VTabsheetBase implements Focusable, Roles.getTabRole().setAriaLabelledbyProperty(getElement(), Id.of(tabCaption.getElement())); - - addFocusHandler(getTabsheet()); - addBlurHandler(getTabsheet()); - addKeyDownHandler(getTabsheet()); } public boolean isHiddenOnServer() { @@ -197,7 +198,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, /** * Toggles the style names for the Tab - * + * * @param selected * true if the Tab is selected * @param first @@ -282,6 +283,11 @@ public class VTabsheet extends VTabsheetBase implements Focusable, } @Override + public HandlerRegistration addMouseDownHandler(MouseDownHandler handler) { + return addDomHandler(handler, MouseDownEvent.getType()); + } + + @Override public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) { return addDomHandler(handler, KeyDownEvent.getType()); } @@ -420,8 +426,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, } - static class TabBar extends ComplexPanel implements ClickHandler, - VCloseHandler { + static class TabBar extends ComplexPanel implements VCloseHandler { private final Element tr = DOM.createTR(); @@ -443,6 +448,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, setStyleName(spacerTd, CLASSNAME + "-spacertd"); DOM.appendChild(tr, spacerTd); DOM.appendChild(spacerTd, DOM.createDiv()); + setElement(el); } @@ -460,10 +466,20 @@ public class VTabsheet extends VTabsheetBase implements Focusable, return DOM.asOld(tr); } + /** + * Gets the number of tabs from the tab bar. + * + * @return the number of tabs from the tab bar. + */ public int getTabCount() { return getWidgetCount(); } + /** + * Adds a tab to the tab bar. + * + * @return the added tab. + */ public Tab addTab() { Tab t = new Tab(this); int tabIndex = getTabCount(); @@ -476,31 +492,18 @@ public class VTabsheet extends VTabsheetBase implements Focusable, t.setStyleNames(false, true); } - t.addClickHandler(this); + getTabsheet().selectionHandler.registerTab(t); + t.setCloseHandler(this); return t; } - @Override - public void onClick(ClickEvent event) { - TabCaption caption = (TabCaption) event.getSource(); - Element targetElement = event.getNativeEvent().getEventTarget() - .cast(); - // the tab should not be focused if the close button was clicked - if (targetElement == caption.getCloseButton()) { - return; - } - - int index = getWidgetIndex(caption.getParent()); - - navigateTab(getTabsheet().focusedTabIndex, index); - getTabsheet().focusedTabIndex = index; - getTabsheet().focusedTab = getTab(index); - getTabsheet().focus(); - getTabsheet().loadTabSheet(index); - } - + /** + * Gets the tab sheet instance where the tab bar is attached to. + * + * @return the tab sheet instance where the tab bar is attached to. + */ public VTabsheet getTabsheet() { return tabsheet; } @@ -538,7 +541,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, getTab(tabsheet.activeTabIndex).recalculateCaptionWidth(); } - public void navigateTab(int fromIndex, int toIndex) { + public Tab navigateTab(int fromIndex, int toIndex) { Tab newNavigated = getTab(toIndex); if (newNavigated == null) { throw new IllegalArgumentException( @@ -553,6 +556,8 @@ public class VTabsheet extends VTabsheetBase implements Focusable, oldNavigated.setStyleNames(oldNavigated.equals(selected), isFirstVisibleTab(fromIndex), false); } + + return newNavigated; } public void removeTab(int i) { @@ -580,7 +585,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, /** * Returns the index of the first visible tab - * + * * @return */ private int getFirstVisibleTab() { @@ -589,7 +594,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, /** * Find the next visible tab. Returns -1 if none is found. - * + * * @param i * @return */ @@ -608,7 +613,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, /** * Find the previous visible tab. Returns -1 if none is found. - * + * * @param i * @return */ @@ -663,7 +668,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, /** For internal use only. May be removed or replaced in the future. */ // tabbar and 'scroller' container public final Element tabs; - Tab focusedTab; + /** * The tabindex property (position in the browser's focus cycle.) Named like * this to avoid confusion with activeTabIndex. @@ -697,9 +702,6 @@ public class VTabsheet extends VTabsheetBase implements Focusable, private String currentStyle; - /** For internal use only. May be removed or replaced in the future. */ - private int focusedTabIndex = 0; - /** * @return Whether the tab could be selected or not. */ @@ -720,11 +722,13 @@ public class VTabsheet extends VTabsheetBase implements Focusable, /** * Load the content of a tab of the provided index. - * + * * @param index * of the tab to load + * + * @return true if the specified sheet gets loaded, otherwise false. */ - public void loadTabSheet(int tabIndex) { + public boolean loadTabSheet(int tabIndex) { if (activeTabIndex != tabIndex && canSelectTab(tabIndex)) { tb.selectTab(tabIndex); @@ -741,12 +745,16 @@ public class VTabsheet extends VTabsheetBase implements Focusable, waitingForResponse = true; tb.getTab(tabIndex).focus(); // move keyboard focus to active tab + + return true; } + + return false; } /** * Returns the currently displayed widget in the tab panel. - * + * * @since 7.2 * @return currently displayed content widget */ @@ -756,7 +764,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, /** * Returns the client to server RPC proxy for the tabsheet. - * + * * @since 7.2 * @return RPC proxy */ @@ -766,10 +774,10 @@ public class VTabsheet extends VTabsheetBase implements Focusable, /** * For internal use only. - * + * * Avoid using this method directly and use appropriate superclass methods * where applicable. - * + * * @deprecated since 7.2 - use more specific methods instead (getRpcProxy(), * getConnectorForWidget(Widget) etc.) * @return ApplicationConnection @@ -799,9 +807,6 @@ public class VTabsheet extends VTabsheetBase implements Focusable, public VTabsheet() { super(CLASSNAME); - addHandler(this, FocusEvent.getType()); - addHandler(this, BlurEvent.getType()); - // Tab scrolling getElement().getStyle().setOverflow(Overflow.HIDDEN); tabs = DOM.createDiv(); @@ -812,18 +817,21 @@ public class VTabsheet extends VTabsheetBase implements Focusable, Roles.getTablistRole().setAriaHiddenState(scroller, true); DOM.setElementProperty(scroller, "className", SCROLLER_CLASSNAME); + scrollerPrev = DOM.createButton(); scrollerPrev.setTabIndex(-1); DOM.setElementProperty(scrollerPrev, "className", SCROLLER_CLASSNAME + "Prev"); Roles.getTablistRole().setAriaHiddenState(scrollerPrev, true); - DOM.sinkEvents(scrollerPrev, Event.ONCLICK); + DOM.sinkEvents(scrollerPrev, Event.ONCLICK | Event.ONMOUSEDOWN); + scrollerNext = DOM.createButton(); scrollerNext.setTabIndex(-1); DOM.setElementProperty(scrollerNext, "className", SCROLLER_CLASSNAME + "Next"); Roles.getTablistRole().setAriaHiddenState(scrollerNext, true); - DOM.sinkEvents(scrollerNext, Event.ONCLICK); + DOM.sinkEvents(scrollerNext, Event.ONCLICK | Event.ONMOUSEDOWN); + DOM.appendChild(getElement(), tabs); // Tabs @@ -856,35 +864,68 @@ public class VTabsheet extends VTabsheetBase implements Focusable, @Override public void onBrowserEvent(Event event) { + com.google.gwt.dom.client.Element eventTarget = DOM + .eventGetTarget(event); + if (event.getTypeInt() == Event.ONCLICK) { + // Tab scrolling - if (isScrolledTabs() && DOM.eventGetTarget(event) == scrollerPrev) { - int newFirstIndex = tb.scrollLeft(scrollerIndex); - if (newFirstIndex != -1) { - scrollerIndex = newFirstIndex; - updateTabScroller(); - } - event.stopPropagation(); - return; - } else if (isClippedTabs() - && DOM.eventGetTarget(event) == scrollerNext) { - int newFirstIndex = tb.scrollRight(scrollerIndex); + if (eventTarget == scrollerPrev || eventTarget == scrollerNext) { + scrollAccordingToScrollTarget(eventTarget); - if (newFirstIndex != -1) { - scrollerIndex = newFirstIndex; - updateTabScroller(); - } event.stopPropagation(); + } + + } else if (event.getTypeInt() == Event.ONMOUSEDOWN) { + + if (eventTarget == scrollerPrev || eventTarget == scrollerNext) { + // In case the focus was previously on a Tab, we need to cancel + // the upcoming blur on the Tab which will follow this mouse + // down event. + focusBlurManager.cancelNextBlurSchedule(); + return; } } + super.onBrowserEvent(event); } + /* + * Scroll the tab bar according to the last scrollTarget (the scroll button + * pressed). + */ + private void scrollAccordingToScrollTarget( + com.google.gwt.dom.client.Element scrollTarget) { + if (scrollTarget == null) { + return; + } + + int newFirstIndex = -1; + + // Scroll left. + if (isScrolledTabs() && scrollTarget == scrollerPrev) { + newFirstIndex = tb.scrollLeft(scrollerIndex); + + // Scroll right. + } else if (isClippedTabs() && scrollTarget == scrollerNext) { + newFirstIndex = tb.scrollRight(scrollerIndex); + } + + if (newFirstIndex != -1) { + scrollerIndex = newFirstIndex; + updateTabScroller(); + } + + // For this to work well, make sure the method gets called only from + // user events. + selectionHandler.focusTabAtIndex(scrollerIndex); + } + /** * Checks if the tab with the selected index has been scrolled out of the * view (on the left side). - * + * * @param index * @return */ @@ -1016,7 +1057,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, /** * Renders the widget content for a tab sheet. - * + * * @param newWidget */ public void renderContent(Widget newWidget) { @@ -1239,64 +1280,467 @@ public class VTabsheet extends VTabsheetBase implements Focusable, } @Override - public void onBlur(BlurEvent event) { - getVTooltip().hideTooltip(); + public void focus() { + getActiveTab().focus(); + } - if (focusedTab != null && focusedTab == event.getSource()) { - focusedTab.removeAssistiveDescription(); - focusedTab = null; - if (connector.hasEventListener(EventId.BLUR)) { - connector.getRpcProxy(FocusAndBlurServerRpc.class).blur(); - } - } + public void blur() { + getActiveTab().blur(); + } + + /* + * Gets the active tab. + */ + private Tab getActiveTab() { + return tb.getTab(activeTabIndex); } @Override - public void onFocus(FocusEvent event) { - if (focusedTab == null && event.getSource() instanceof Tab) { - focusedTab = (Tab) event.getSource(); + public void setConnector(AbstractComponentConnector connector) { + super.setConnector(connector); + + focusBlurManager.connector = connector; + } + + /* + * The focus and blur manager instance. + */ + private FocusBlurManager focusBlurManager = new FocusBlurManager(); + + /* + * Generate the correct focus/blur events for the main TabSheet component + * (#14304). + * + * The TabSheet must fire one focus event when the user clicks on the tab + * bar (i.e. inner TabBar class) containing the Tabs or when the focus is + * provided to the TabSheet by any means. Also one blur event should be + * fired only when the user leaves the tab bar. After the user focus on the + * tab bar and before leaving it, no matter how many times he's pressing the + * Tabs or the scroll buttons, the TabSheet component should not fire any of + * those blur/focus events. + * + * The only focusable elements contained in the tab bar are the Tabs (see + * inner class Tab). The reason is the accessibility support. + * + * Having this in mind, the chosen solution path for our problem is to match + * a sequence of focus/blur events on the tabs, choose only the first focus + * and last blur events and pass only those further to the main component. + * Any consecutive blur/focus events on 2 Tabs must be ignored. + * + * Because in a blur event we don't know whether or not a focus will follow, + * we just defer a command initiated on the blur event to wait and see if + * any focus will appear. The command will be executed after the next focus, + * so if no focus was triggered in the mean while it'll submit the blur + * event to the main component, otherwise it'll do nothing, so the main + * component will not generate the blur.. + */ + private static class FocusBlurManager { + + // The real tab with focus on it. If the focus goes to another element + // in the page this will be null. + private Tab focusedTab; + + /* + * Gets the focused tab. + */ + private Tab getFocusedTab() { + return focusedTab; + } + + /* + * Sets the local field tracking the focused tab. + */ + private void setFocusedTab(Tab focusedTab) { + this.focusedTab = focusedTab; + } + + /* + * The ultimate focus/blur event dispatcher. + */ + private AbstractComponentConnector connector; + + /** + * Delegate method for the onFocus event occurring on Tab. + * + * @since + * @param newFocusTab + * the new focused tab. + * @see #onBlur(Tab) + */ + public void onFocus(Tab newFocusTab) { + if (connector.hasEventListener(EventId.FOCUS)) { - connector.getRpcProxy(FocusAndBlurServerRpc.class).focus(); + + // Send the focus event only first time when we focus on any + // tab. The focused tab will be reseted on the last blur. + if (focusedTab == null) { + connector.getRpcProxy(FocusAndBlurServerRpc.class).focus(); + } + } + + cancelLastBlurSchedule(); + + setFocusedTab(newFocusTab); + } + + /** + * Delegate method for the onBlur event occurring on Tab. + * + * @param blurSource + * the source of the blur. + * + * @see #onFocus(Tab) + */ + public void onBlur(Tab blurSource) { + if (focusedTab != null && focusedTab == blurSource) { + + if (connector.hasEventListener(EventId.BLUR)) { + scheduleBlur(focusedTab); + } + } + } + + /* + * The last blur command to be executed. + */ + private BlurCommand blurCommand; + + /* + * Execute the final blur command. + */ + private class BlurCommand implements Command { + + /* + * The blur source. + */ + private Tab blurSource; + + /** + * Create the blur command using the blur source. + * + * @param blurSource + * the source. + * @param focusedTabProvider + * provides the current focused tab. + */ + public BlurCommand(Tab blurSource) { + this.blurSource = blurSource; + } + + /** + * Stop the command from being executed. + * + * @since + */ + public void stopSchedule() { + blurSource = null; } - if (focusedTab.hasTooltip()) { - focusedTab.setAssistiveDescription(getVTooltip().getUniqueId()); - getVTooltip().showAssistive(focusedTab.getTooltipInfo()); + /** + * Schedule the command for a deferred execution. + * + * @since + */ + public void scheduleDeferred() { + Scheduler.get().scheduleDeferred(this); + } + + @Override + public void execute() { + + Tab focusedTab = getFocusedTab(); + + if (blurSource == null) { + return; + } + + // The focus didn't change since this blur triggered, so + // the new focused element is not a tab. + if (focusedTab == blurSource) { + + // We're certain there's no focus anymore. + focusedTab.removeAssistiveDescription(); + setFocusedTab(null); + + connector.getRpcProxy(FocusAndBlurServerRpc.class).blur(); + } + + // Call this to set it to null and be consistent. + cancelLastBlurSchedule(); } } + + /* + * Schedule a new blur event for a deferred execution. + */ + private void scheduleBlur(Tab blurSource) { + + if (nextBlurScheduleCancelled) { + + // This will set the stopNextBlurCommand back to false as well. + cancelLastBlurSchedule(); + + // Reset the status. + nextBlurScheduleCancelled = false; + return; + } + + cancelLastBlurSchedule(); + + blurCommand = new BlurCommand(blurSource); + blurCommand.scheduleDeferred(); + } + + /** + * Remove the last blur deferred command from execution. + */ + public void cancelLastBlurSchedule() { + if (blurCommand != null) { + blurCommand.stopSchedule(); + blurCommand = null; + } + + // We really want to make sure this flag gets reseted at any time + // when something interact with the blur manager and ther's no blur + // command scheduled (as we just canceled it). + nextBlurScheduleCancelled = false; + } + + /** + * Cancel the next scheduled execution. This method must be called only + * from an event occurring before the onBlur event. It's the case of IE + * which doesn't trigger the focus event, so we're using this approach + * to cancel the next blur event prior it's execution, calling the + * method from mouse down event. + */ + public void cancelNextBlurSchedule() { + + // Make sure there's still no other command to be executed. + cancelLastBlurSchedule(); + + nextBlurScheduleCancelled = true; + } + + /* + * Flag that the next deferred command won't get executed. This is + * useful in case of IE where the user focus event don't fire and we're + * using the mouse down event to track the focus. But the mouse down + * event triggers before the blur, so we need to cancel the deferred + * execution in advance. + */ + private boolean nextBlurScheduleCancelled = false; + } @Override - public void focus() { - tb.getTab(activeTabIndex).focus(); + public void onBlur(BlurEvent event) { + selectionHandler.onBlur(event); } - public void blur() { - tb.getTab(activeTabIndex).blur(); + @Override + public void onFocus(FocusEvent event) { + selectionHandler.onFocus(event); } @Override public void onKeyDown(KeyDownEvent event) { - if (event.getSource() instanceof Tab) { - int keycode = event.getNativeEvent().getKeyCode(); - - if (!event.isAnyModifierKeyDown()) { - if (keycode == getPreviousTabKey()) { - selectPreviousTab(); - event.stopPropagation(); - } else if (keycode == getNextTabKey()) { - selectNextTab(); - event.stopPropagation(); - } else if (keycode == getCloseTabKey()) { - Tab tab = tb.getTab(activeTabIndex); - if (tab.isClosable()) { - tab.onClose(); + selectionHandler.onKeyDown(event); + } + + /* + * The tabs selection handler instance. + */ + private final TabSelectionHandler selectionHandler = new TabSelectionHandler(); + + /* + * Handle the events for selecting the tabs. + */ + private class TabSelectionHandler implements FocusHandler, BlurHandler, + KeyDownHandler, ClickHandler, MouseDownHandler { + + /** For internal use only. May be removed or replaced in the future. */ + // The current visible focused index. + private int focusedTabIndex = 0; + + /** + * Register the tab to the selection handler. + * + * @param tab + * the tab to register. + */ + public void registerTab(Tab tab) { + + // TODO: change VTabsheet.this to this in 7.3 + tab.addBlurHandler(VTabsheet.this); + tab.addFocusHandler(VTabsheet.this); + tab.addKeyDownHandler(VTabsheet.this); + + tab.addClickHandler(this); + tab.addMouseDownHandler(this); + } + + @Override + public void onBlur(final BlurEvent event) { + + getVTooltip().hideTooltip(); + + Object blurSource = event.getSource(); + + if (blurSource instanceof Tab) { + focusBlurManager.onBlur((Tab) blurSource); + } + } + + @Override + public void onFocus(FocusEvent event) { + + if (event.getSource() instanceof Tab) { + Tab focusSource = (Tab) event.getSource(); + focusBlurManager.onFocus(focusSource); + + if (focusSource.hasTooltip()) { + focusSource.setAssistiveDescription(getVTooltip() + .getUniqueId()); + getVTooltip().showAssistive(focusSource.getTooltipInfo()); + } + + } + } + + @Override + public void onClick(ClickEvent event) { + + // IE doesn't trigger focus when click, so we need to make sure + // the previous blur deferred command will get killed. + focusBlurManager.cancelLastBlurSchedule(); + + TabCaption caption = (TabCaption) event.getSource(); + Element targetElement = event.getNativeEvent().getEventTarget() + .cast(); + // the tab should not be focused if the close button was clicked + if (targetElement == caption.getCloseButton()) { + return; + } + + int index = tb.getWidgetIndex(caption.getParent()); + + tb.navigateTab(focusedTabIndex, index); + + focusedTabIndex = index; + + if (!loadTabSheet(index)) { + + // This needs to be called at the end, as the activeTabIndex + // is set in the loadTabSheet. + focus(); + } + } + + @Override + public void onMouseDown(MouseDownEvent event) { + + if (event.getSource() instanceof Tab) { + + // IE doesn't trigger focus when click, so we need to make sure + // the + // next blur deferred command will get killed. + focusBlurManager.cancelNextBlurSchedule(); + } + } + + @Override + public void onKeyDown(KeyDownEvent event) { + if (event.getSource() instanceof Tab) { + int keycode = event.getNativeEvent().getKeyCode(); + + if (!event.isAnyModifierKeyDown()) { + if (keycode == getPreviousTabKey()) { + selectPreviousTab(); + event.stopPropagation(); + + } else if (keycode == getNextTabKey()) { + selectNextTab(); + event.stopPropagation(); + + } else if (keycode == getCloseTabKey()) { + Tab tab = tb.getTab(activeTabIndex); + if (tab.isClosable()) { + tab.onClose(); + } + + } else if (keycode == getSelectTabKey()) { + loadTabSheet(focusedTabIndex); + + // Prevent the page from scrolling when hitting space + // (select key) to select the current tab. + event.preventDefault(); } - } else if (keycode == getSelectTabKey()) { - loadTabSheet(focusedTabIndex); } } } + + /* + * Left arrow key selection. + */ + private void selectPreviousTab() { + int newTabIndex = focusedTabIndex; + // Find the previous visible and enabled tab if any. + do { + newTabIndex--; + } while (newTabIndex >= 0 && !canSelectTab(newTabIndex)); + + if (newTabIndex >= 0) { + keySelectTab(newTabIndex); + } + } + + /* + * Right arrow key selection. + */ + private void selectNextTab() { + int newTabIndex = focusedTabIndex; + // Find the next visible and enabled tab if any. + do { + newTabIndex++; + } while (newTabIndex < getTabCount() && !canSelectTab(newTabIndex)); + + if (newTabIndex < getTabCount()) { + keySelectTab(newTabIndex); + } + } + + /* + * Select the specified tab using left/right key. + */ + private void keySelectTab(int newTabIndex) { + Tab tab = tb.getTab(newTabIndex); + if (tab == null) { + return; + } + + // Focus the tab, otherwise the selected one will loose focus and + // TabSheet will get blurred. + focusTabAtIndex(newTabIndex); + + tb.navigateTab(focusedTabIndex, newTabIndex); + + focusedTabIndex = newTabIndex; + } + + /** + * Focus the specified tab. Make sure to call this only from user + * events, otherwise will break things. + * + * @param tabIndex + * the index of the tab to set. + */ + void focusTabAtIndex(int tabIndex) { + Tab tabToFocus = tb.getTab(tabIndex); + if (tabToFocus != null) { + tabToFocus.focus(); + } + } + } /** @@ -1307,8 +1751,17 @@ public class VTabsheet extends VTabsheetBase implements Focusable, return KeyCodes.KEY_LEFT; } + /** + * Gets the key to activate the selected tab when navigating using + * previous/next (left/right) keys. + * + * @return the key to activate the selected tab. + * + * @see #getNextTabKey() + * @see #getPreviousTabKey() + */ protected int getSelectTabKey() { - return 32; // Space key + return KeyCodes.KEY_SPACE; } /** @@ -1327,66 +1780,32 @@ public class VTabsheet extends VTabsheetBase implements Focusable, return KeyCodes.KEY_DELETE; } - private void selectPreviousTab() { - int newTabIndex = focusedTabIndex; - // Find the previous visible and enabled tab if any. - do { - newTabIndex--; - } while (newTabIndex >= 0 && !canSelectTab(newTabIndex)); - - if (newTabIndex >= 0) { - tb.navigateTab(focusedTabIndex, newTabIndex); - focusedTabIndex = newTabIndex; - - // If this TabSheet already has focus, set the new selected tab - // as focused. - if (focusedTab != null) { - focusedTab = tb.getTab(focusedTabIndex); - focusedTab.focus(); - } - } - } - - private void selectNextTab() { - int newTabIndex = focusedTabIndex; - // Find the next visible and enabled tab if any. - do { - newTabIndex++; - } while (newTabIndex < getTabCount() && !canSelectTab(newTabIndex)); - - if (newTabIndex < getTabCount()) { + private void scrollIntoView(Tab tab) { - tb.navigateTab(focusedTabIndex, newTabIndex); - focusedTabIndex = newTabIndex; + if (!tab.isHiddenOnServer()) { - // If this TabSheet already has focus, set the new selected tab - // as focused. - if (focusedTab != null) { - focusedTab = tb.getTab(focusedTabIndex); - focusedTab.focus(); - } - } - } + // Check for visibility first as clipped tabs to the right are + // always visible. + // On IE8 a tab with false visibility would have the bounds of the + // full TabBar. + if (!tab.isVisible()) { + while (!tab.isVisible()) { + scrollerIndex = tb.scrollLeft(scrollerIndex); + } + updateTabScroller(); - private void scrollIntoView(Tab tab) { - if (!tab.isHiddenOnServer()) { - if (isClipped(tab)) { + } else if (isClipped(tab)) { while (isClipped(tab) && scrollerIndex != -1) { scrollerIndex = tb.scrollRight(scrollerIndex); } updateTabScroller(); - } else if (!tab.isVisible()) { - while (!tab.isVisible()) { - scrollerIndex = tb.scrollLeft(scrollerIndex); - } - updateTabScroller(); } } } /** * Makes tab bar visible. - * + * * @since 7.2 */ public void showTabs() { @@ -1397,7 +1816,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, /** * Makes tab bar invisible. - * + * * @since 7.2 */ public void hideTabs() { diff --git a/client/src/com/vaadin/client/ui/VWindow.java b/client/src/com/vaadin/client/ui/VWindow.java index 495e230156..7223e4ac83 100644 --- a/client/src/com/vaadin/client/ui/VWindow.java +++ b/client/src/com/vaadin/client/ui/VWindow.java @@ -245,6 +245,20 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner, * state. */ setTabStopEnabled(doTabStop); + + // Fix for #14413. Any pseudo elements inside these elements are not + // visible on initial render unless we shake the DOM. + if (BrowserInfo.get().isIE8()) { + closeBox.getStyle().setDisplay(Display.NONE); + maximizeRestoreBox.getStyle().setDisplay(Display.NONE); + Scheduler.get().scheduleFinally(new Command() { + @Override + public void execute() { + closeBox.getStyle().clearDisplay(); + maximizeRestoreBox.getStyle().clearDisplay(); + } + }); + } } @Override diff --git a/client/src/com/vaadin/client/ui/draganddropwrapper/DragAndDropWrapperConnector.java b/client/src/com/vaadin/client/ui/draganddropwrapper/DragAndDropWrapperConnector.java index afb521b141..f222721e24 100644 --- a/client/src/com/vaadin/client/ui/draganddropwrapper/DragAndDropWrapperConnector.java +++ b/client/src/com/vaadin/client/ui/draganddropwrapper/DragAndDropWrapperConnector.java @@ -17,8 +17,12 @@ package com.vaadin.client.ui.draganddropwrapper; import java.util.HashMap; import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.ComponentConnector; +import com.vaadin.client.ConnectorMap; import com.vaadin.client.Paintable; import com.vaadin.client.UIDL; import com.vaadin.client.VConsole; @@ -81,6 +85,25 @@ public class DragAndDropWrapperConnector extends CustomComponentConnector getWidget().dragStartMode = uidl .getIntAttribute(DragAndDropWrapperConstants.DRAG_START_MODE); + + String dragImageComponentConnectorId = uidl + .getStringAttribute(DragAndDropWrapperConstants.DRAG_START_COMPONENT_ATTRIBUTE); + + ComponentConnector connector = null; + if (dragImageComponentConnectorId != null) { + connector = (ComponentConnector) ConnectorMap.get(client) + .getConnector(dragImageComponentConnectorId); + + if (connector == null) { + getLogger().log( + Level.WARNING, + "DragAndDropWrapper drag image component" + + " connector now found. Make sure the" + + " component is attached."); + } else { + getWidget().setDragAndDropWidget(connector.getWidget()); + } + } getWidget().initDragStartMode(); getWidget().html5DataFlavors = uidl .getMapAttribute(DragAndDropWrapperConstants.HTML5_DATA_FLAVORS); @@ -95,4 +118,7 @@ public class DragAndDropWrapperConnector extends CustomComponentConnector return (VDragAndDropWrapper) super.getWidget(); } + private static Logger getLogger() { + return Logger.getLogger(DragAndDropWrapperConnector.class.getName()); + } } diff --git a/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java b/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java index 5b428574e2..e38054e3e4 100644 --- a/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java +++ b/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java @@ -28,6 +28,7 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { private static final String IE10_WINDOWS_8 = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)"; private static final String IE11_WINDOWS_7 = "Mozilla/5.0 (Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; rv:11.0) like Gecko"; + private static final String IE11_WINDOWS_PHONE_8_1_UPDATE = "Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920) Like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537"; // "Version/" was added in 10.00 private static final String OPERA964_WINDOWS = "Opera/9.64(Windows NT 5.1; U; en) Presto/2.1.1"; @@ -396,6 +397,16 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { assertWindows(bd); } + public void testIE11WindowsPhone81Update() { + VBrowserDetails bd = new VBrowserDetails(IE11_WINDOWS_PHONE_8_1_UPDATE); + assertTrident(bd); + assertEngineVersion(bd, 7); + assertIE(bd); + assertBrowserMajorVersion(bd, 11); + assertBrowserMinorVersion(bd, 0); + assertWindows(bd); + } + /* * Helper methods below */ diff --git a/server/src/com/vaadin/ui/DragAndDropWrapper.java b/server/src/com/vaadin/ui/DragAndDropWrapper.java index 3d3356b338..0e2e8f6d2f 100644 --- a/server/src/com/vaadin/ui/DragAndDropWrapper.java +++ b/server/src/com/vaadin/ui/DragAndDropWrapper.java @@ -180,10 +180,17 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget, * the wrapper will no longer work. */ HTML5, + + /** + * Uses the component defined in + * {@link #setDragImageComponent(Component)} as the drag image. + */ + COMPONENT_OTHER, } private final Map<String, Object> html5DataFlavors = new LinkedHashMap<String, Object>(); private DragStartMode dragStartMode = DragStartMode.NONE; + private Component dragImageComponent = null; private Set<String> sentIds = new HashSet<String>(); @@ -227,6 +234,19 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget, public void paintContent(PaintTarget target) throws PaintException { target.addAttribute(DragAndDropWrapperConstants.DRAG_START_MODE, dragStartMode.ordinal()); + + if (dragStartMode.equals(DragStartMode.COMPONENT_OTHER)) { + if (dragImageComponent != null) { + target.addAttribute( + DragAndDropWrapperConstants.DRAG_START_COMPONENT_ATTRIBUTE, + dragImageComponent.getConnectorId()); + } else { + throw new IllegalArgumentException( + "DragStartMode.COMPONENT_OTHER set but no component " + + "was defined. Please set a component using DragAnd" + + "DropWrapper.setDragStartComponent(Component)."); + } + } if (getDropHandler() != null) { getDropHandler().getAcceptCriterion().paint(target); } @@ -300,6 +320,27 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget, return dragStartMode; } + /** + * Sets the component that will be used as the drag image. Only used when + * wrapper is set to {@link DragStartMode#COMPONENT_OTHER} + * + * @param dragImageComponent + */ + public void setDragImageComponent(Component dragImageComponent) { + this.dragImageComponent = dragImageComponent; + markAsDirty(); + } + + /** + * Gets the component that will be used as the drag image. Only used when + * wrapper is set to {@link DragStartMode#COMPONENT_OTHER} + * + * @return <code>null</code> if no component is set. + */ + public Component getDragImageComponent() { + return dragImageComponent; + } + final class ProxyReceiver implements StreamVariable { private String id; diff --git a/server/src/com/vaadin/ui/themes/ValoTheme.java b/server/src/com/vaadin/ui/themes/ValoTheme.java index ad949c6a32..d6bd97ed72 100644 --- a/server/src/com/vaadin/ui/themes/ValoTheme.java +++ b/server/src/com/vaadin/ui/themes/ValoTheme.java @@ -25,9 +25,10 @@ import com.vaadin.ui.Table.ColumnHeaderMode; * </p> * * <p> - * These styles are only available if the Valo theme (or any of it's variants) - * is built with the <code>$valo-include-common-stylenames</code> Sass variable - * set to <code>true</code>. + * These styles are only available if the + * <code>$v-included-additional-styles</code> Sass list variable contains the + * name of the component for that additional style name (e.g. + * <code>button, textfield, table</code>). * </p> * * <p> @@ -149,6 +150,12 @@ public class ValoTheme { public static final String LABEL_NO_MARGIN = "no-margin"; /** + * Tiny font size. Suitable for additional/supplementary UI text. Can be + * combined with any other Label style. + */ + public static final String LABEL_TINY = "tiny"; + + /** * Small font size. Suitable for additional/supplementary UI text. Can be * combined with any other Label style. */ @@ -161,6 +168,12 @@ public class ValoTheme { public static final String LABEL_LARGE = "large"; /** + * Huge font size. Suitable for important/prominent UI text. Can be combined + * with any other Label style. + */ + public static final String LABEL_HUGE = "huge"; + + /** * Lighter font weight. Suitable for additional/supplementary UI text. Can * be combined with any other Label style. */ @@ -173,6 +186,11 @@ public class ValoTheme { public static final String LABEL_BOLD = "bold"; /** + * Colored text. Can be combined with any other Label style. + */ + public static final String LABEL_COLORED = "colored"; + + /** * Success badge style. Adds a border around the label and an icon next to * the text. Suitable for UI notifications that need to in the direct * context of some component. Can be combined with any other Label style. @@ -252,6 +270,11 @@ public class ValoTheme { public static final String BUTTON_LINK = "link"; /** + * Tiny size button. Can be combined with any other Button style. + */ + public static final String BUTTON_TINY = "tiny"; + + /** * Small size button. Can be combined with any other Button style. */ public static final String BUTTON_SMALL = "small"; @@ -262,6 +285,11 @@ public class ValoTheme { public static final String BUTTON_LARGE = "large"; /** + * Huge size button. Can be combined with any other Button style. + */ + public static final String BUTTON_HUGE = "huge"; + + /** * Align the icon to the right side of the button caption. Can be combined * with any other Button style. */ @@ -301,6 +329,11 @@ public class ValoTheme { **************************************************************************/ /** + * Tiny size text field. Can be combined with any other TextField style. + */ + public static final String TEXTFIELD_TINY = "tiny"; + + /** * Small size text field. Can be combined with any other TextField style. */ public static final String TEXTFIELD_SMALL = "small"; @@ -311,6 +344,11 @@ public class ValoTheme { public static final String TEXTFIELD_LARGE = "large"; /** + * Huge size text field. Can be combined with any other TextField style. + */ + public static final String TEXTFIELD_HUGE = "huge"; + + /** * Removes the border and background from the text field. Can be combined * with any other TextField style. */ @@ -341,6 +379,11 @@ public class ValoTheme { **************************************************************************/ /** + * Tiny size text area. Can be combined with any other TextArea style. + */ + public static final String TEXTAREA_TINY = "tiny"; + + /** * Small size text area. Can be combined with any other TextArea style. */ public static final String TEXTAREA_SMALL = "small"; @@ -351,6 +394,11 @@ public class ValoTheme { public static final String TEXTAREA_LARGE = "large"; /** + * Huge size text area. Can be combined with any other TextArea style. + */ + public static final String TEXTAREA_HUGE = "huge"; + + /** * Removes the border and background from the text area. Can be combined * with any other TextArea style. */ @@ -375,6 +423,11 @@ public class ValoTheme { **************************************************************************/ /** + * Tiny size date field. Can be combined with any other DateField style. + */ + public static final String DATEFIELD_TINY = "tiny"; + + /** * Small size date field. Can be combined with any other DateField style. */ public static final String DATEFIELD_SMALL = "small"; @@ -385,6 +438,11 @@ public class ValoTheme { public static final String DATEFIELD_LARGE = "large"; /** + * Huge size date field. Can be combined with any other DateField style. + */ + public static final String DATEFIELD_HUGE = "huge"; + + /** * Removes the border and background from the date field. Can be combined * with any other DateField style. */ @@ -409,6 +467,11 @@ public class ValoTheme { **************************************************************************/ /** + * Tiny size combo box. Can be combined with any other ComboBox style. + */ + public static final String COMBOBOX_TINY = "tiny"; + + /** * Small size combo box. Can be combined with any other ComboBox style. */ public static final String COMBOBOX_SMALL = "small"; @@ -419,6 +482,11 @@ public class ValoTheme { public static final String COMBOBOX_LARGE = "large"; /** + * Huge size combo box. Can be combined with any other ComboBox style. + */ + public static final String COMBOBOX_HUGE = "huge"; + + /** * Removes the border and background from the combo box. Can be combined * with any other ComboBox style. */ diff --git a/shared/src/com/vaadin/shared/VBrowserDetails.java b/shared/src/com/vaadin/shared/VBrowserDetails.java index 3680e4168e..81a39cdedc 100644 --- a/shared/src/com/vaadin/shared/VBrowserDetails.java +++ b/shared/src/com/vaadin/shared/VBrowserDetails.java @@ -68,19 +68,19 @@ public class VBrowserDetails implements Serializable { isGecko = userAgent.indexOf("gecko") != -1 && userAgent.indexOf("webkit") == -1 && userAgent.indexOf("trident/") == -1; - isWebKit = userAgent.indexOf("applewebkit") != -1; isPresto = userAgent.indexOf(" presto/") != -1; isTrident = userAgent.indexOf("trident/") != -1; + isWebKit = !isTrident && userAgent.indexOf("applewebkit") != -1; // browser name isChrome = userAgent.indexOf(" chrome/") != -1; - isSafari = !isChrome && userAgent.indexOf("safari") != -1; isOpera = userAgent.indexOf("opera") != -1; isIE = userAgent.indexOf("msie") != -1 && !isOpera && (userAgent.indexOf("webtv") == -1); // IE 11 no longer contains MSIE in the user agent isIE = isIE || isTrident; + isSafari = !isChrome && !isIE && userAgent.indexOf("safari") != -1; isFirefox = userAgent.indexOf(" firefox/") != -1; // chromeframe diff --git a/shared/src/com/vaadin/shared/ui/draganddropwrapper/DragAndDropWrapperConstants.java b/shared/src/com/vaadin/shared/ui/draganddropwrapper/DragAndDropWrapperConstants.java index 8dd8ef513e..9dda86ad73 100644 --- a/shared/src/com/vaadin/shared/ui/draganddropwrapper/DragAndDropWrapperConstants.java +++ b/shared/src/com/vaadin/shared/ui/draganddropwrapper/DragAndDropWrapperConstants.java @@ -25,4 +25,6 @@ public class DragAndDropWrapperConstants implements Serializable { @Deprecated public static final String DRAG_START_MODE = "dragStartMode"; + public static final String DRAG_START_COMPONENT_ATTRIBUTE = "dragStartComponent"; + } diff --git a/uitest/build.xml b/uitest/build.xml index 84f44a2d72..e81983f1f5 100644 --- a/uitest/build.xml +++ b/uitest/build.xml @@ -11,6 +11,7 @@ <property name="module.name" value="vaadin-uitest" /> <property name="uitest.dir" location="${vaadin.basedir}/uitest" /> <property name="result.dir" value="result" /> + <property name="theme.result.dir" value="${result.dir}/VAADIN/themes" /> <property name="result.war" location="${result.dir}/lib/${module.name}-${vaadin.version}.war" /> <path id="classpath.compile.custom"> @@ -91,7 +92,7 @@ </target> - <target name="war" depends="dependencies, compile, testing-widgetset"> + <target name="war" depends="dependencies, compile, compile-test-themes, testing-widgetset"> <property name="result.dir" location="result" /> <property name="classes" location="${result.dir}/classes" /> <property name="WebContent.dir" location="${vaadin.basedir}/WebContent" /> @@ -121,10 +122,13 @@ <fileset refid="common.files.for.all.jars" /> <fileset dir="${result.dir}"> <include name="VAADIN/widgetsets/**/*" /> + <include name="VAADIN/themes/tests-valo*/**" /> </fileset> <fileset dir="${WebContent.dir}"> <include name="statictestfiles/**" /> <include name="VAADIN/themes/tests-*/**" /> + <!-- Scss themes compiled and included above --> + <exclude name="VAADIN/themes/tests-valo*/**" /> <include name="VAADIN/themes/reindeer-tests/**" /> <include name="VAADIN/jquery.atmosphere.js" /> <include name="WEB-INF/*.xml" /> @@ -192,43 +196,43 @@ </target> <target name="test-server" depends="clean-testbench-errors"> - <property name="war.file" location="${vaadin.basedir}/result/artifacts/${vaadin.version}/vaadin-uitest/vaadin-uitest-${vaadin.version}.war" /> - <parallel> - <daemons> - <ant antfile="${uitest.dir}/vaadin-server.xml" inheritall="true" inheritrefs="true" target="deploy-and-start" /> - </daemons> - <sequential> - <ant antfile="${uitest.dir}/integration_tests.xml" target="integration-test-all" inheritall="false" inheritrefs="false"> - <property name="demo.war" value="${war.file}" /> - </ant> - </sequential> - </parallel> + <property name="war.file" location="${vaadin.basedir}/result/artifacts/${vaadin.version}/vaadin-uitest/vaadin-uitest-${vaadin.version}.war" /> + <parallel> + <daemons> + <ant antfile="${uitest.dir}/vaadin-server.xml" inheritall="true" inheritrefs="true" target="deploy-and-start" /> + </daemons> + <sequential> + <ant antfile="${uitest.dir}/integration_tests.xml" target="integration-test-all" inheritall="false" inheritrefs="false"> + <property name="demo.war" value="${war.file}" /> + </ant> + </sequential> + </parallel> </target> <target name="test-tb2" depends="clean-testbench-errors"> - <property name="war.file" location="${vaadin.basedir}/result/artifacts/${vaadin.version}/vaadin-uitest/vaadin-uitest-${vaadin.version}.war" /> - <parallel> - <daemons> - <ant antfile="${uitest.dir}/vaadin-server.xml" inheritall="true" inheritrefs="true" target="deploy-and-start" /> - </daemons> - <sequential> - <ant antfile="${uitest.dir}/vaadin-server.xml" target="wait-for-startup" /> - <ant antfile="${uitest.dir}/test.xml" target="tb2-tests" /> - </sequential> - </parallel> + <property name="war.file" location="${vaadin.basedir}/result/artifacts/${vaadin.version}/vaadin-uitest/vaadin-uitest-${vaadin.version}.war" /> + <parallel> + <daemons> + <ant antfile="${uitest.dir}/vaadin-server.xml" inheritall="true" inheritrefs="true" target="deploy-and-start" /> + </daemons> + <sequential> + <ant antfile="${uitest.dir}/vaadin-server.xml" target="wait-for-startup" /> + <ant antfile="${uitest.dir}/test.xml" target="tb2-tests" /> + </sequential> + </parallel> </target> <target name="test-tb3" depends="clean-testbench-errors"> - <property name="war.file" location="${vaadin.basedir}/result/artifacts/${vaadin.version}/vaadin-uitest/vaadin-uitest-${vaadin.version}.war" /> - <parallel> - <daemons> - <ant antfile="${uitest.dir}/vaadin-server.xml" inheritall="true" inheritrefs="true" target="deploy-and-start" /> - </daemons> - <sequential> - <ant antfile="${uitest.dir}/vaadin-server.xml" target="wait-for-startup" /> - <ant antfile="${uitest.dir}/tb3test.xml" target="run-all-tb3-tests" inheritall="true" /> - </sequential> - </parallel> + <property name="war.file" location="${vaadin.basedir}/result/artifacts/${vaadin.version}/vaadin-uitest/vaadin-uitest-${vaadin.version}.war" /> + <parallel> + <daemons> + <ant antfile="${uitest.dir}/vaadin-server.xml" inheritall="true" inheritrefs="true" target="deploy-and-start" /> + </daemons> + <sequential> + <ant antfile="${uitest.dir}/vaadin-server.xml" target="wait-for-startup" /> + <ant antfile="${uitest.dir}/tb3test.xml" target="run-all-tb3-tests" inheritall="true" /> + </sequential> + </parallel> </target> <target name="clean-testbench-errors"> @@ -241,4 +245,71 @@ </delete> </target> + <target name="compile-test-themes"> + <antcall target="compile-theme"> + <param name="theme" value="tests-valo" /> + </antcall> + <antcall target="compile-theme"> + <param name="theme" value="tests-valo-dark" /> + </antcall> + <antcall target="compile-theme"> + <param name="theme" value="tests-valo-metro" /> + </antcall> + <antcall target="compile-theme"> + <param name="theme" value="tests-valo-flat" /> + </antcall> + <antcall target="compile-theme"> + <param name="theme" value="tests-valo-flatdark" /> + </antcall> + <antcall target="compile-theme"> + <param name="theme" value="tests-valo-facebook" /> + </antcall> + <antcall target="compile-theme"> + <param name="theme" value="tests-valo-blueprint" /> + </antcall> + + </target> + <target name="compile-theme" depends="copy-theme"> + <fail unless="theme" message="You must give the theme name to compile in the 'theme' parameter" /> + + <ivy:resolve log="download-only" resolveid="common" conf="compile-theme" /> + <ivy:cachepath pathid="classpath.compile.theme" conf="compile-theme" /> + <ivy:cachepath pathid="classpath.runtime.theme" conf="build" /> + + <echo>Compiling ${theme}</echo> + <mkdir dir="${theme.result.dir}" /> + + <!-- compile the theme --> + <java classname="com.vaadin.buildhelpers.CompileTheme" classpathref="classpath.compile.theme" failonerror="yes" fork="yes" maxmemory="512m"> + <arg value="--theme" /> + <arg value="${theme}" /> + <arg value="--theme-folder" /> + <arg value="${theme.result.dir}" /> + <arg value="--version" /> + <arg value="${vaadin.version}" /> + <jvmarg value="-Xss8M" /> + <jvmarg value="-XX:MaxPermSize=256M" /> + <jvmarg value="-Djava.awt.headless=true" /> + </java> + + </target> + + <target name="copy-theme"> + <fail unless="theme" message="You must give the theme name to copy n the 'theme' parameter" /> + <property name="theme.source.dir" location="../WebContent/VAADIN/themes" /> + + <copy todir="${theme.result.dir}"> + <fileset dir="${theme.source.dir}"> + <include name="${theme}/**/*.scss" /> + </fileset> + <filterset refid="filter-vaadin.version" /> + </copy> + <copy todir="${theme.result.dir}"> + <fileset dir="${theme.source.dir}"> + <exclude name="${theme}/**/*.scss" /> + </fileset> + </copy> + </target> + + </project> diff --git a/uitest/ivy.xml b/uitest/ivy.xml index 020543c53f..9af209662c 100644 --- a/uitest/ivy.xml +++ b/uitest/ivy.xml @@ -15,6 +15,7 @@ <conf name="build-provided" visibility="private" /> <conf name="ide" visibility="private" /> <conf name="jetty-run" visibility="private" /> + <conf name="compile-theme" visibility="private" /> </configurations> <publications> <artifact type="war" ext="war" /> @@ -99,6 +100,13 @@ <!-- This should be removed once tests have been updated to use lang3 --> <dependency org="commons-lang" name="commons-lang" rev="2.6" conf="build,ide -> default" /> + + <dependency org="com.vaadin" name="vaadin-sass-compiler" + rev="${vaadin.sass.version}" conf="compile-theme->default" /> + + <dependency org="com.vaadin" name="vaadin-buildhelpers" + rev="${vaadin.version}" conf="compile-theme->build" /> + </dependencies> </ivy-module> diff --git a/uitest/src/com/vaadin/tests/applicationservlet/UIProviderInitParameter.html b/uitest/src/com/vaadin/tests/applicationservlet/UIProviderInitParameter.html deleted file mode 100644 index 8a5f89cbad..0000000000 --- a/uitest/src/com/vaadin/tests/applicationservlet/UIProviderInitParameter.html +++ /dev/null @@ -1,39 +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>/uiprovider</td> - <td></td> -</tr> -<!--Test that UI parameter is used by default--> -<tr> - <td>assertText</td> - <td>vaadin=uiprovider::/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VLabel[0]</td> - <td>Tests whether the testing server is run with assertions enabled.</td> -</tr> -<!--Test that UIProvider parameter is more important than UI parameter--> -<tr> - <td>open</td> - <td>/uiprovider/test</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=uiprovider::/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VLabel[0]</td> - <td>Test for basic JavaScript component functionality.</td> -</tr> - -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/applicationservlet/UIProviderInitParameterTest.java b/uitest/src/com/vaadin/tests/applicationservlet/UIProviderInitParameterTest.java new file mode 100644 index 0000000000..8197bbe8b8 --- /dev/null +++ b/uitest/src/com/vaadin/tests/applicationservlet/UIProviderInitParameterTest.java @@ -0,0 +1,58 @@ +/* + * Copyright 2000-2014 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.applicationservlet; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; + +import com.vaadin.testbench.elements.LabelElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class UIProviderInitParameterTest extends MultiBrowserTest { + + @Test + public void testDefault() { + // Test that UI parameter is used by default + openTestURL(); + + List<LabelElement> labels = $(LabelElement.class).all(); + assertTrue("unexpected amount of labels", labels.size() > 2); + + LabelElement label = labels.get(labels.size() - 1); + String message = "Tests whether the testing server is run with assertions enabled."; + assertEquals("unexpected text found", message, label.getText()); + } + + @Test + public void testExtended() { + // Test that UIProvider parameter is more important than UI parameter + driver.get(getTestUrl().replace("uiprovider", "uiprovider/test")); + + LabelElement label = $(LabelElement.class).first(); + String message = "Test for basic JavaScript component functionality."; + assertEquals("unexpected text found", message, label.getText()); + } + + @Override + protected String getDeploymentPath() { + return "/uiprovider"; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/combobox/ComboBoxSuggestionPopupClose.java b/uitest/src/com/vaadin/tests/components/combobox/ComboBoxSuggestionPopupClose.java new file mode 100644 index 0000000000..253d6a0d1e --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/combobox/ComboBoxSuggestionPopupClose.java @@ -0,0 +1,29 @@ +package com.vaadin.tests.components.combobox; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.ComboBox; + +public class ComboBoxSuggestionPopupClose extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + final ComboBox select = new ComboBox("ComboBox"); + select.addItem("one"); + select.addItem("two"); + select.addItem("three"); + addComponent(select); + } + + @Override + protected String getTestDescription() { + return "Closing the suggestion popup using Enter key is " + + "broken in combobox when opening popup using Enter " + + "key and not changin the selection using arrows"; + } + + @Override + protected Integer getTicketNumber() { + return 14379; + } +} diff --git a/uitest/src/com/vaadin/tests/components/combobox/ComboBoxSuggestionPopupCloseTest.java b/uitest/src/com/vaadin/tests/components/combobox/ComboBoxSuggestionPopupCloseTest.java new file mode 100644 index 0000000000..5e9e076cac --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/combobox/ComboBoxSuggestionPopupCloseTest.java @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2014 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.combobox; + +import static org.junit.Assert.assertFalse; +import static org.openqa.selenium.Keys.ARROW_DOWN; +import static org.openqa.selenium.Keys.ENTER; + +import org.junit.Test; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.By; +import com.vaadin.testbench.elements.ComboBoxElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * @author Vaadin Ltd + */ +public class ComboBoxSuggestionPopupCloseTest extends MultiBrowserTest { + + private WebElement selectTextbox; + + @Test + public void closeSuggestionPopupTest() throws Exception { + openTestURL(); + + waitForElementVisible(By.className("v-filterselect")); + + selectTextbox = $(ComboBoxElement.class).first().findElement( + By.vaadin("#textbox")); + selectTextbox.click(); + + // open popup and select first element + sendKeys(new Keys[] { ARROW_DOWN, ARROW_DOWN, ENTER }); + + // open popup and hit enter to close it + sendKeys(new Keys[] { ARROW_DOWN, ENTER }); + + assertFalse(isElementPresent(By.className("v-filterselect-suggestmenu"))); + + } + + private void sendKeys(Keys[] keys) throws Exception { + for (Keys key : keys) { + selectTextbox.sendKeys(key); + // wait a while between the key presses, at least PhantomJS fails if + // they are sent too fast + sleep(10); + } + } +}; diff --git a/uitest/src/com/vaadin/tests/components/datefield/DateFieldChangeResolutionTest.java b/uitest/src/com/vaadin/tests/components/datefield/DateFieldChangeResolutionTest.java index 6820410059..e3c85224c0 100644 --- a/uitest/src/com/vaadin/tests/components/datefield/DateFieldChangeResolutionTest.java +++ b/uitest/src/com/vaadin/tests/components/datefield/DateFieldChangeResolutionTest.java @@ -99,7 +99,10 @@ public class DateFieldChangeResolutionTest extends MultiBrowserTest { } private void checkHeaderAndBody(Resolution resolution, - boolean textFieldIsEmpty) { + boolean textFieldIsEmpty) throws Exception { + // Popup date field has all kinds of strange timers on the + // client side + sleep(100); // Open the popup calendar, perform checks and close the popup. openPopupDateField(); if (resolution.getCalendarField() >= Resolution.MONTH diff --git a/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldExtendedRange.html b/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldExtendedRange.html deleted file mode 100644 index 2783ed2aa3..0000000000 --- a/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldExtendedRange.html +++ /dev/null @@ -1,136 +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>PopupDateFieldExtendedRange</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">PopupDateFieldExtendedRange</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.components.datefield.PopupDateFieldExtendedRange?restartApplication</td> - <td></td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestscomponentsdatefieldPopupDateFieldExtendedRange::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VPopupCalendar[0]#popupButton</td> - <td>7,16</td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td>popup1-01-2011</td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestscomponentsdatefieldPopupDateFieldExtendedRange::Root/VOverlay[0]/VCalendarPanel[0]#prevmon</td> - <td>8,7</td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td>popup1-12-2010</td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestscomponentsdatefieldPopupDateFieldExtendedRange::Root/VOverlay[0]/VCalendarPanel[0]#prevy</td> - <td>12,6</td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td>popup1-12-2009</td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestscomponentsdatefieldPopupDateFieldExtendedRange::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VPopupCalendar[0]#popupButton</td> - <td>10,13</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runcomvaadintestscomponentsdatefieldPopupDateFieldExtendedRange::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestscomponentsdatefieldPopupDateFieldExtendedRange::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VPopupCalendar[0]#popupButton</td> - <td>14,13</td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td>popup2-02-2010</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runcomvaadintestscomponentsdatefieldPopupDateFieldExtendedRange::Root/VOverlay[0]/VCalendarPanel[0]</td> - <td>down</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runcomvaadintestscomponentsdatefieldPopupDateFieldExtendedRange::Root/VOverlay[0]/VCalendarPanel[0]</td> - <td>down</td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td>popup2-03-2010</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runcomvaadintestscomponentsdatefieldPopupDateFieldExtendedRange::Root/VOverlay[0]/VCalendarPanel[0]</td> - <td>left</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runcomvaadintestscomponentsdatefieldPopupDateFieldExtendedRange::Root/VOverlay[0]/VCalendarPanel[0]</td> - <td>left</td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td>popup2-02-2010-again</td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestscomponentsdatefieldPopupDateFieldExtendedRange::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VPopupCalendar[0]#popupButton</td> - <td>7,16</td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestscomponentsdatefieldPopupDateFieldExtendedRange::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[2]/VPopupCalendar[0]#popupButton</td> - <td>17,10</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runcomvaadintestscomponentsdatefieldPopupDateFieldExtendedRange::Root/VOverlay[0]/VCalendarPanel[0]</td> - <td>shift left</td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td>popup3-01-2010</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runcomvaadintestscomponentsdatefieldPopupDateFieldExtendedRange::Root/VOverlay[0]/VCalendarPanel[0]</td> - <td>shift down</td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td>popup3-01-2009</td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestscomponentsdatefieldPopupDateFieldExtendedRange::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[2]/VPopupCalendar[0]#popupButton</td> - <td>10,8</td> -</tr> -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldExtendedRange.java b/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldExtendedRange.java index a12bdfa44c..2608e6e081 100644 --- a/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldExtendedRange.java +++ b/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldExtendedRange.java @@ -3,20 +3,21 @@ package com.vaadin.tests.components.datefield; import java.util.Calendar; import java.util.Locale; -import com.vaadin.tests.components.TestBase; +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.datefield.Resolution; +import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; -import com.vaadin.ui.DateField; import com.vaadin.ui.PopupDateField; @SuppressWarnings("serial") -public class PopupDateFieldExtendedRange extends TestBase { +public class PopupDateFieldExtendedRange extends AbstractTestUI { private Calendar date = Calendar.getInstance(); @Override - protected void setup() { + protected void setup(VaadinRequest request) { date.set(2011, 0, 1); getLayout().setSpacing(true); @@ -52,7 +53,7 @@ public class PopupDateFieldExtendedRange extends TestBase { } @Override - protected String getDescription() { + protected String getTestDescription() { return "Show a few days of the preceding and following months in the datefield popup"; } @@ -63,7 +64,7 @@ public class PopupDateFieldExtendedRange extends TestBase { private PopupDateField makeDateField() { PopupDateField pdf = new PopupDateField(); - pdf.setResolution(DateField.RESOLUTION_DAY); + pdf.setResolution(Resolution.DAY); pdf.setValue(date.getTime()); return pdf; } diff --git a/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldExtendedRangeTest.java b/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldExtendedRangeTest.java new file mode 100644 index 0000000000..6d22048d32 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldExtendedRangeTest.java @@ -0,0 +1,510 @@ +/* + * Copyright 2000-2014 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.datefield; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.testbench.By; +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.DateFieldElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Tests contents and functionality of PopupDateField's popup. + * + * @author Vaadin Ltd + */ +public class PopupDateFieldExtendedRangeTest extends MultiBrowserTest { + + @Override + @Before + public void setup() throws Exception { + super.setup(); + openTestURL(); + } + + @Test + public void testFirstDateField() { + List<DateFieldElement> dateFields = $(DateFieldElement.class).all(); + assertEquals("unexpected amount of datefields", 3, dateFields.size()); + + DateFieldElement dateField = dateFields.get(0); + + // open the popup + dateField.findElement(By.tagName("button")).click(); + + assertTrue("popup not found when there should be one", + isElementPresent(By.className("v-datefield-popup"))); + + // verify contents + WebElement popup = findElement(By.className("v-datefield-popup")); + assertEquals( + "unexpected month", + "tammikuu 2011", + popup.findElements( + By.className("v-datefield-calendarpanel-month")).get(1) + .getText()); + List<WebElement> headerElements = popup.findElement( + By.className("v-datefield-calendarpanel-weekdays")) + .findElements(By.tagName("td")); + List<WebElement> weekdays = new ArrayList<WebElement>(); + for (WebElement headerElement : headerElements) { + if ("columnheader".equals(headerElement.getAttribute("role"))) { + weekdays.add(headerElement); + } + } + assertEquals("unexpected weekday count", 7, weekdays.size()); + assertEquals("unexpected first day of week", "MA", weekdays.get(0) + .getText()); + assertEquals( + "unexpected weeknumber count", + 0, + popup.findElements( + By.className("v-datefield-calendarpanel-weeknumber")) + .size()); + assertEquals( + "unexpected selection", + "1", + popup.findElement( + By.className("v-datefield-calendarpanel-day-selected")) + .getText()); + assertEquals( + "unexpected focus", + "1", + popup.findElement( + By.className("v-datefield-calendarpanel-day-focused")) + .getText()); + List<WebElement> days = popup.findElements(By + .className("v-datefield-calendarpanel-day")); + assertEquals("unexpected day count", 42, days.size()); + assertEquals("unexpected day content", "27", days.get(0).getText()); + assertEquals("unexpected day content", "4", days.get(8).getText()); + assertEquals("unexpected day content", "21", days.get(25).getText()); + assertEquals("unexpected day content", "6", days.get(41).getText()); + + // move to the previous month + popup.findElement(By.className("v-datefield-calendarpanel-prevmonth")) + .findElement(By.tagName("button")).click(); + + // verify contents + assertEquals( + "unexpected month", + "joulukuu 2010", + popup.findElements( + By.className("v-datefield-calendarpanel-month")).get(1) + .getText()); + assertEquals( + "unexpected selection", + "1", + popup.findElement( + By.className("v-datefield-calendarpanel-day-selected")) + .getText()); + assertEquals( + "unexpected focus", + 0, + popup.findElements( + By.className("v-datefield-calendarpanel-day-focused")) + .size()); + days = popup + .findElements(By.className("v-datefield-calendarpanel-day")); + assertEquals("unexpected day count", 42, days.size()); + assertEquals("unexpected day content", "29", days.get(0).getText()); + assertEquals("unexpected day content", "7", days.get(8).getText()); + assertEquals("unexpected day content", "24", days.get(25).getText()); + assertEquals("unexpected day content", "9", days.get(41).getText()); + + // move to the previous year + popup.findElement(By.className("v-datefield-calendarpanel-prevyear")) + .findElement(By.tagName("button")).click(); + + // verify contents + assertEquals( + "unexpected month", + "joulukuu 2009", + popup.findElements( + By.className("v-datefield-calendarpanel-month")).get(1) + .getText()); + assertEquals( + "unexpected selection", + 0, + popup.findElements( + By.className("v-datefield-calendarpanel-day-selected")) + .size()); + assertEquals( + "unexpected focus", + 0, + popup.findElements( + By.className("v-datefield-calendarpanel-day-focused")) + .size()); + days = popup + .findElements(By.className("v-datefield-calendarpanel-day")); + assertEquals("unexpected day count", 42, days.size()); + assertEquals("unexpected day content", "30", days.get(0).getText()); + assertEquals("unexpected day content", "8", days.get(8).getText()); + assertEquals("unexpected day content", "25", days.get(25).getText()); + assertEquals("unexpected day content", "10", days.get(41).getText()); + + // close the popup by clicking the button again + dateField.findElement(By.tagName("button")).click(); + + // TODO: remove this once #14405 has been fixed + if (!getBrowsersExcludingIE().contains(getDesiredCapabilities())) { + // click something else outside the popup to close it + dateField.findElement(By.tagName("input")).click(); + } + + assertFalse("popup found when there should be none", + isElementPresent(By.className("v-datefield-popup"))); + } + + @Test + public void testSecondDateField() throws InterruptedException { + DateFieldElement dateField = $(DateFieldElement.class).all().get(1); + ButtonElement button = $(ButtonElement.class).first(); + + // change the date + button.click(); + sleep(100); + + // open the popup + dateField.findElement(By.tagName("button")).click(); + + assertTrue("popup not found when there should be one", + isElementPresent(By.className("v-datefield-popup"))); + + // verify contents + WebElement popup = findElement(By.className("v-datefield-popup")); + assertEquals( + "unexpected month", + "February 2010", + popup.findElements( + By.className("v-datefield-calendarpanel-month")).get(1) + .getText()); + List<WebElement> headerElements = popup.findElement( + By.className("v-datefield-calendarpanel-weekdays")) + .findElements(By.tagName("td")); + List<WebElement> weekdays = new ArrayList<WebElement>(); + for (WebElement headerElement : headerElements) { + if ("columnheader".equals(headerElement.getAttribute("role"))) { + weekdays.add(headerElement); + } + } + assertEquals("unexpected weekday count", 7, weekdays.size()); + assertEquals("unexpected first day of week", "SUN", weekdays.get(0) + .getText()); + assertEquals( + "unexpected weeknumber count", + 0, + popup.findElements( + By.className("v-datefield-calendarpanel-weeknumber")) + .size()); + assertEquals( + "unexpected selection", + "16", + popup.findElement( + By.className("v-datefield-calendarpanel-day-selected")) + .getText()); + assertEquals( + "unexpected focus", + "16", + popup.findElement( + By.className("v-datefield-calendarpanel-day-focused")) + .getText()); + List<WebElement> days = popup.findElements(By + .className("v-datefield-calendarpanel-day")); + assertEquals("unexpected day count", 42, days.size()); + assertEquals("unexpected day content", "31", days.get(0).getText()); + assertEquals("unexpected day content", "8", days.get(8).getText()); + assertEquals("unexpected day content", "25", days.get(25).getText()); + assertEquals("unexpected day content", "13", days.get(41).getText()); + + // navigate down + WebElement popupBody = popup.findElement(By + .className("v-datefield-calendarpanel")); + popupBody.sendKeys(Keys.ARROW_DOWN); + + // ensure the focus changed + assertEquals( + "unexpected focus", + "23", + popup.findElement( + By.className("v-datefield-calendarpanel-day-focused")) + .getText()); + + // navigate down + popupBody.sendKeys(Keys.ARROW_DOWN); + + // verify contents + assertEquals( + "unexpected month", + "March 2010", + popup.findElements( + By.className("v-datefield-calendarpanel-month")).get(1) + .getText()); + assertEquals( + "unexpected selection", + 0, + popup.findElements( + By.className("v-datefield-calendarpanel-day-selected")) + .size()); + assertEquals( + "unexpected focus", + "2", + popup.findElement( + By.className("v-datefield-calendarpanel-day-focused")) + .getText()); + days = popup + .findElements(By.className("v-datefield-calendarpanel-day")); + assertEquals("unexpected day count", 42, days.size()); + assertEquals("unexpected day content", "28", days.get(0).getText()); + assertEquals("unexpected day content", "8", days.get(8).getText()); + assertEquals("unexpected day content", "25", days.get(25).getText()); + assertEquals("unexpected day content", "10", days.get(41).getText()); + + // navigate left + popupBody = popup + .findElement(By.className("v-datefield-calendarpanel")); + popupBody.sendKeys(Keys.ARROW_LEFT); + + // ensure the focus changed + assertEquals( + "unexpected focus", + "1", + popup.findElement( + By.className("v-datefield-calendarpanel-day-focused")) + .getText()); + + // navigate left + popupBody.sendKeys(Keys.ARROW_LEFT); + + // verify contents + assertEquals( + "unexpected month", + "February 2010", + popup.findElements( + By.className("v-datefield-calendarpanel-month")).get(1) + .getText()); + assertEquals( + "unexpected selection", + "16", + popup.findElement( + By.className("v-datefield-calendarpanel-day-selected")) + .getText()); + assertEquals( + "unexpected focus", + "28", + popup.findElement( + By.className("v-datefield-calendarpanel-day-focused")) + .getText()); + days = popup + .findElements(By.className("v-datefield-calendarpanel-day")); + assertEquals("unexpected day count", 42, days.size()); + assertEquals("unexpected day content", "31", days.get(0).getText()); + assertEquals("unexpected day content", "8", days.get(8).getText()); + assertEquals("unexpected day content", "25", days.get(25).getText()); + assertEquals("unexpected day content", "13", days.get(41).getText()); + + // close the popup by clicking the input field + dateField.findElement(By.tagName("input")).click(); + + assertFalse("popup found when there should be none", + isElementPresent(By.className("v-datefield-popup"))); + } + + @Test + public void testThirdDateField() throws InterruptedException { + DateFieldElement dateField = $(DateFieldElement.class).all().get(2); + ButtonElement button = $(ButtonElement.class).first(); + + // change the date + button.click(); + sleep(100); + + // open the popup + dateField.findElement(By.tagName("button")).click(); + + assertTrue("popup not found when there should be one", + isElementPresent(By.className("v-datefield-popup"))); + + // verify contents + WebElement popup = findElement(By.className("v-datefield-popup")); + assertEquals( + "unexpected month", + "helmikuu 2010", + popup.findElements( + By.className("v-datefield-calendarpanel-month")).get(1) + .getText()); + List<WebElement> headerElements = popup.findElement( + By.className("v-datefield-calendarpanel-weekdays")) + .findElements(By.tagName("td")); + List<WebElement> weekdays = new ArrayList<WebElement>(); + for (WebElement headerElement : headerElements) { + if ("columnheader".equals(headerElement.getAttribute("role"))) { + weekdays.add(headerElement); + } + } + assertEquals("unexpected weekday count", 7, weekdays.size()); + assertEquals("unexpected first day of week", "MA", weekdays.get(0) + .getText()); + List<WebElement> weeknumbers = popup.findElements(By + .className("v-datefield-calendarpanel-weeknumber")); + assertEquals("unexpected weeknumber count", 6, weeknumbers.size()); + assertEquals("unexpected weeknumber content", "5", weeknumbers.get(0) + .getText()); + assertEquals("unexpected weeknumber content", "10", weeknumbers.get(5) + .getText()); + assertEquals( + "unexpected selection", + "16", + popup.findElement( + By.className("v-datefield-calendarpanel-day-selected")) + .getText()); + assertEquals( + "unexpected focus", + "16", + popup.findElement( + By.className("v-datefield-calendarpanel-day-focused")) + .getText()); + List<WebElement> days = popup.findElements(By + .className("v-datefield-calendarpanel-day")); + assertEquals("unexpected day count", 42, days.size()); + assertEquals("unexpected day content", "1", days.get(0).getText()); + assertEquals("unexpected day content", "9", days.get(8).getText()); + assertEquals("unexpected day content", "26", days.get(25).getText()); + assertEquals("unexpected day content", "14", days.get(41).getText()); + + // navigate to previous month + WebElement popupBody = popup.findElement(By + .className("v-datefield-calendarpanel")); + new Actions(driver).keyDown(Keys.SHIFT).perform(); + popupBody.sendKeys(Keys.ARROW_LEFT); + new Actions(driver).keyUp(Keys.SHIFT).perform(); + + // TODO: remove this once #14406 has been fixed + if (!getBrowsersExcludingIE().contains(getDesiredCapabilities()) + && !Browser.IE8.getDesiredCapabilities().equals( + getDesiredCapabilities())) { + popup.findElement( + By.className("v-datefield-calendarpanel-prevmonth")) + .findElement(By.tagName("button")).click(); + } + + // verify contents + assertEquals( + "unexpected month", + "tammikuu 2010", + popup.findElements( + By.className("v-datefield-calendarpanel-month")).get(1) + .getText()); + weeknumbers = popup.findElements(By + .className("v-datefield-calendarpanel-weeknumber")); + assertEquals("unexpected weeknumber count", 6, weeknumbers.size()); + assertEquals("unexpected weeknumber content", "53", weeknumbers.get(0) + .getText()); + assertEquals("unexpected weeknumber content", "5", weeknumbers.get(5) + .getText()); + assertEquals( + "unexpected selection", + 0, + popup.findElements( + By.className("v-datefield-calendarpanel-day-selected")) + .size()); + // TODO: remove this check once #14406 has been fixed -- clicking the + // button instead of navigating with arrow keys steals the focus + if (getBrowsersExcludingIE().contains(getDesiredCapabilities()) + || Browser.IE8.getDesiredCapabilities().equals( + getDesiredCapabilities())) { + assertEquals( + "unexpected focus", + "16", + popup.findElement( + By.className("v-datefield-calendarpanel-day-focused")) + .getText()); + } + days = popup + .findElements(By.className("v-datefield-calendarpanel-day")); + assertEquals("unexpected day count", 42, days.size()); + assertEquals("unexpected day content", "28", days.get(0).getText()); + assertEquals("unexpected day content", "5", days.get(8).getText()); + assertEquals("unexpected day content", "22", days.get(25).getText()); + assertEquals("unexpected day content", "7", days.get(41).getText()); + + // navigate to previous year + new Actions(driver).keyDown(Keys.SHIFT).perform(); + popupBody.sendKeys(Keys.ARROW_DOWN); + new Actions(driver).keyUp(Keys.SHIFT).perform(); + + // TODO: remove this once #14406 has been fixed + popup.findElement(By.className("v-datefield-calendarpanel-prevyear")) + .findElement(By.tagName("button")).click(); + + // verify contents + assertEquals( + "unexpected month", + "tammikuu 2009", + popup.findElements( + By.className("v-datefield-calendarpanel-month")).get(1) + .getText()); + weeknumbers = popup.findElements(By + .className("v-datefield-calendarpanel-weeknumber")); + assertEquals("unexpected weeknumber count", 6, weeknumbers.size()); + assertEquals("unexpected weeknumber content", "1", weeknumbers.get(0) + .getText()); + assertEquals("unexpected weeknumber content", "6", weeknumbers.get(5) + .getText()); + assertEquals( + "unexpected selection", + 0, + popup.findElements( + By.className("v-datefield-calendarpanel-day-selected")) + .size()); + // TODO: remove this check once #14406 has been fixed -- clicking the + // button instead of navigating with arrow keys steals the focus + if (false) { + assertEquals( + "unexpected focus", + "16", + popup.findElement( + By.className("v-datefield-calendarpanel-day-focused")) + .getText()); + } + days = popup + .findElements(By.className("v-datefield-calendarpanel-day")); + assertEquals("unexpected day count", 42, days.size()); + assertEquals("unexpected day content", "29", days.get(0).getText()); + assertEquals("unexpected day content", "6", days.get(8).getText()); + assertEquals("unexpected day content", "23", days.get(25).getText()); + assertEquals("unexpected day content", "8", days.get(41).getText()); + + // close the popup by clicking an unrelated element + button.click(); + + assertFalse("popup found when there should be none", + isElementPresent(By.className("v-datefield-popup"))); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragStartModes.java b/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragStartModes.java index b143ddf2dc..8539f70b17 100644 --- a/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragStartModes.java +++ b/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragStartModes.java @@ -3,26 +3,53 @@ package com.vaadin.tests.components.draganddropwrapper; import com.vaadin.tests.components.TestBase; import com.vaadin.tests.util.TestUtils; import com.vaadin.ui.Component; +import com.vaadin.ui.CssLayout; import com.vaadin.ui.DragAndDropWrapper; import com.vaadin.ui.DragAndDropWrapper.DragStartMode; import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalLayout; public class DragStartModes extends TestBase { @Override protected void setup() { - TestUtils.injectCSS(getMainWindow(), - ".v-ddwrapper { background: #ACF; }"); + TestUtils + .injectCSS(getMainWindow(), + ".v-ddwrapper { background: #ACF; } .extra{ background: #FFA500; }"); addComponent(makeWrapper(DragStartMode.NONE)); addComponent(makeWrapper(DragStartMode.COMPONENT)); addComponent(makeWrapper(DragStartMode.WRAPPER)); addComponent(makeWrapper(DragStartMode.HTML5)); + addComponent(makeOtherComponentWrapper(DragStartMode.COMPONENT_OTHER)); addComponent(new Label("Drop here")); } + private Component makeOtherComponentWrapper(DragStartMode componentOther) { + VerticalLayout parent = new VerticalLayout(); + parent.setWidth("200px"); + parent.setSpacing(true); + + CssLayout header = new CssLayout(); + header.addComponent(new Label("Drag start mode : COMPONENT_OTHER")); + header.setSizeUndefined(); + + DragAndDropWrapper wrapper = new DragAndDropWrapper(header); + wrapper.setDragStartMode(DragStartMode.COMPONENT_OTHER); + wrapper.setDragImageComponent(parent); + wrapper.setId("label" + "COMPONENT_OTHER"); + parent.addComponent(wrapper); + + Label extra = new Label( + "Extra label that is not part of the wrapper. This should be dragged along with COMPONENT_OTHER."); + extra.addStyleName("extra"); + parent.addComponent(extra); + + return parent; + } + private Component makeWrapper(DragStartMode mode) { Label label = new Label("Drag start mode: " + mode); label.setId("label" + mode); diff --git a/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragStartModesTest.java b/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragStartModesTest.java index 25aef1b815..ba27ee293e 100644 --- a/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragStartModesTest.java +++ b/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragStartModesTest.java @@ -31,6 +31,7 @@ public class DragStartModesTest extends MultiBrowserTest { WebElement dropTarget = vaadinElement("/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[0]"); dragToTarget("COMPONENT", dropTarget); dragToTarget("WRAPPER", dropTarget); + dragToTarget("COMPONENT_OTHER", dropTarget); } private void dragToTarget(String dragMode, WebElement dropTarget) diff --git a/uitest/src/com/vaadin/tests/components/table/SortLabelsInTable.java b/uitest/src/com/vaadin/tests/components/table/SortLabelsInTable.java index 0dc8584169..499cce58c8 100644 --- a/uitest/src/com/vaadin/tests/components/table/SortLabelsInTable.java +++ b/uitest/src/com/vaadin/tests/components/table/SortLabelsInTable.java @@ -16,14 +16,16 @@ package com.vaadin.tests.components.table; import com.vaadin.data.Item; -import com.vaadin.tests.components.TestBase; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.ui.Label; import com.vaadin.ui.Table; -public class SortLabelsInTable extends TestBase { +public class SortLabelsInTable extends AbstractTestUI { + @SuppressWarnings("unchecked") @Override - protected void setup() { + protected void setup(VaadinRequest request) { Table t = new Table("A table with a text column and a Label column"); t.addContainerProperty("text", String.class, null); t.addContainerProperty("label", Label.class, null); @@ -37,9 +39,8 @@ public class SortLabelsInTable extends TestBase { } @Override - protected String getDescription() { - // TODO Auto-generated method stub - return null; + protected String getTestDescription() { + return "Tests that Labels are sorted in the same way than Strings are."; } @Override diff --git a/uitest/src/com/vaadin/tests/components/table/SortLabelsInTableTest.java b/uitest/src/com/vaadin/tests/components/table/SortLabelsInTableTest.java new file mode 100644 index 0000000000..54b5cad9b2 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/SortLabelsInTableTest.java @@ -0,0 +1,93 @@ +/* + * Copyright 2000-2014 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.table; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.vaadin.testbench.elements.TableElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Tests sorting labels in table. + * + * @author Vaadin Ltd + */ +public class SortLabelsInTableTest extends MultiBrowserTest { + + @Test + public void testSorting() { + openTestURL(); + + TableElement table = $(TableElement.class).first(); + + // check unsorted + assertEquals("Text 0", table.getCell(0, 0).getText()); + assertEquals("Label 0", table.getCell(0, 1).getText()); + assertEquals("Text 14", table.getCell(14, 0).getText()); + assertEquals("Label 14", table.getCell(14, 1).getText()); + + // sort by first column (ascending order) + table.getHeaderCell(0).click(); + + // check sorted + assertEquals("Text 0", table.getCell(0, 0).getText()); + assertEquals("Label 0", table.getCell(0, 1).getText()); + assertEquals("Text 10", table.getCell(2, 0).getText()); + assertEquals("Label 10", table.getCell(2, 1).getText()); + assertEquals("Text 19", table.getCell(11, 0).getText()); + assertEquals("Label 19", table.getCell(11, 1).getText()); + assertEquals("Text 4", table.getCell(14, 0).getText()); + assertEquals("Label 4", table.getCell(14, 1).getText()); + + // sort by first column (descending order) + table.getHeaderCell(0).click(); + + // check sorted + assertEquals("Text 9", table.getCell(0, 0).getText()); + assertEquals("Label 9", table.getCell(0, 1).getText()); + assertEquals("Text 19", table.getCell(8, 0).getText()); + assertEquals("Label 19", table.getCell(8, 1).getText()); + assertEquals("Text 13", table.getCell(14, 0).getText()); + assertEquals("Label 13", table.getCell(14, 1).getText()); + + // sort by second column (descending order) + table.getHeaderCell(1).click(); + + // check no change + assertEquals("Text 9", table.getCell(0, 0).getText()); + assertEquals("Label 9", table.getCell(0, 1).getText()); + assertEquals("Text 19", table.getCell(8, 0).getText()); + assertEquals("Label 19", table.getCell(8, 1).getText()); + assertEquals("Text 13", table.getCell(14, 0).getText()); + assertEquals("Label 13", table.getCell(14, 1).getText()); + + // sort by second column (ascending order) + table.getHeaderCell(1).click(); + + // check back to first sorting results + assertEquals("Text 0", table.getCell(0, 0).getText()); + assertEquals("Label 0", table.getCell(0, 1).getText()); + assertEquals("Text 10", table.getCell(2, 0).getText()); + assertEquals("Label 10", table.getCell(2, 1).getText()); + assertEquals("Text 19", table.getCell(11, 0).getText()); + assertEquals("Label 19", table.getCell(11, 1).getText()); + assertEquals("Text 4", table.getCell(14, 0).getText()); + assertEquals("Label 4", table.getCell(14, 1).getText()); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/table/TableRowScrolledBottom.html b/uitest/src/com/vaadin/tests/components/table/TableRowScrolledBottom.html deleted file mode 100644 index 5116fceb49..0000000000 --- a/uitest/src/com/vaadin/tests/components/table/TableRowScrolledBottom.html +++ /dev/null @@ -1,52 +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="http://localhost:8888/" /> -<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.table.TableRowScrolledBottom?restartApplication</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runcomvaadintestscomponentstableTableRowScrolledBottom::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VButton[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>pause</td> - <td>500</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestscomponentstableTableRowScrolledBottom::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VScrollTable[0]/VScrollTable$FocusableScrollContextPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[44]/VLabel[0]</td> - <td>This is a test item with long text so that there is something to see Nr. 100. This text must be long otherwise the timing issue on Firefox does not occur. This works fine in IE</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runcomvaadintestscomponentstableTableRowScrolledBottom::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>pause</td> - <td>500</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestscomponentstableTableRowScrolledBottom::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VScrollTable[0]/VScrollTable$FocusableScrollContextPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[44]/VLabel[0]</td> - <td>This is a test item with long text so that there is something to see Nr. 200. This text must be long otherwise the timing issue on Firefox does not occur. This works fine in IE</td> -</tr> - -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/components/table/TableRowScrolledBottom.java b/uitest/src/com/vaadin/tests/components/table/TableRowScrolledBottom.java index 7d48dfa11e..e1fe4d0514 100644 --- a/uitest/src/com/vaadin/tests/components/table/TableRowScrolledBottom.java +++ b/uitest/src/com/vaadin/tests/components/table/TableRowScrolledBottom.java @@ -1,15 +1,19 @@ package com.vaadin.tests.components.table; +import com.vaadin.server.VaadinRequest; import com.vaadin.shared.ui.label.ContentMode; -import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.ui.Button; import com.vaadin.ui.Label; import com.vaadin.ui.Table; -public class TableRowScrolledBottom extends TestBase { +public class TableRowScrolledBottom extends AbstractTestUI { + + final static String part1 = "This is a test item with long text so that there is something to see Nr. "; + final static String part2 = ". This text must be long otherwise the timing issue on Firefox does not occur. This works fine in IE"; @Override - protected void setup() { + protected void setup(VaadinRequest request) { final Table table = new Table(); table.setSizeFull(); @@ -24,12 +28,8 @@ public class TableRowScrolledBottom extends TestBase { public void buttonClick(Button.ClickEvent event) { for (int j = 0; j < 100; j++) { ++i; - table.addItem( - new Object[] { new Label( - "This is a test item with long text so that there is something to see Nr. <b>" - + i - + "</b>. This text must be long otherwise the timing issue on Firefox does not occur. This works fine in IE", - ContentMode.HTML) }, i); + table.addItem(new Object[] { new Label(part1 + "<b>" + i + + "</b>" + part2, ContentMode.HTML) }, i); table.setCurrentPageFirstItemIndex(table .getContainerDataSource().size() - 1); } @@ -42,7 +42,7 @@ public class TableRowScrolledBottom extends TestBase { } @Override - protected String getDescription() { + protected String getTestDescription() { return "Table should be scrolled to bottom when adding rows and updating currentPageFirstItemIndex to last item"; } diff --git a/uitest/src/com/vaadin/tests/components/table/TableRowScrolledBottomTest.java b/uitest/src/com/vaadin/tests/components/table/TableRowScrolledBottomTest.java new file mode 100644 index 0000000000..0fad02b410 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/TableRowScrolledBottomTest.java @@ -0,0 +1,73 @@ +/* + * Copyright 2000-2014 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.table; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.TableElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Tests that adding long labels to a Table and scrolling to the bottom works as + * intended. + * + * @author Vaadin Ltd + */ +public class TableRowScrolledBottomTest extends MultiBrowserTest { + + @Test + public void testScrolling() throws IOException, InterruptedException { + openTestURL(); + + ButtonElement button = $(ButtonElement.class).first(); + TableElement table = $(TableElement.class).first(); + + // initialise contents + button.click(); + sleep(500); + + List<WebElement> rows = table.findElement(By.className("v-table-body")) + .findElements(By.tagName("tr")); + + // check that the final row is the one intended + WebElement finalRow = rows.get(rows.size() - 1); + WebElement label = finalRow.findElement(By.className("v-label")); + assertEquals(TableRowScrolledBottom.part1 + 100 + + TableRowScrolledBottom.part2, label.getText()); + + // add more rows + button.click(); + sleep(500); + + rows = table.findElement(By.className("v-table-body")).findElements( + By.tagName("tr")); + + // check that the final row is the one intended + finalRow = rows.get(rows.size() - 1); + label = finalRow.findElement(By.className("v-label")); + assertEquals(TableRowScrolledBottom.part1 + 200 + + TableRowScrolledBottom.part2, label.getText()); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/table/TextFieldRelativeWidth.html b/uitest/src/com/vaadin/tests/components/table/TextFieldRelativeWidth.html deleted file mode 100644 index 6e3d86175a..0000000000 --- a/uitest/src/com/vaadin/tests/components/table/TextFieldRelativeWidth.html +++ /dev/null @@ -1,63 +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>TextFieldRelativeWidth</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">TextFieldRelativeWidth</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.components.table.TextFieldRelativeWidth</td> - <td></td> -</tr> -<!-- Workaround for Opera 10.50 CSS loading problem --> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.components.table.TextFieldRelativeWidth</td> - <td></td> -</tr> -<tr> - <td>waitForVaadin</td> - <td></td> - <td></td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runcomvaadintestscomponentstableTextFieldRelativeWidth::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/VScrollTable$FocusableScrollContextPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[2]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>waitForVaadin</td> - <td></td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runcomvaadintestscomponentstableTextFieldRelativeWidth::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/VScrollTable$FocusableScrollContextPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[4]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>waitForVaadin</td> - <td></td> - <td></td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td></td> -</tr> - -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/components/table/TextFieldRelativeWidth.java b/uitest/src/com/vaadin/tests/components/table/TextFieldRelativeWidth.java index 5c7479d060..4799d05415 100644 --- a/uitest/src/com/vaadin/tests/components/table/TextFieldRelativeWidth.java +++ b/uitest/src/com/vaadin/tests/components/table/TextFieldRelativeWidth.java @@ -1,19 +1,19 @@ package com.vaadin.tests.components.table; import com.vaadin.data.Item; -import com.vaadin.data.Property; import com.vaadin.data.util.IndexedContainer; -import com.vaadin.tests.components.TestBase; +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.Component; import com.vaadin.ui.Table; import com.vaadin.ui.TextField; -public class TextFieldRelativeWidth extends TestBase { +public class TextFieldRelativeWidth extends AbstractTestUI { @Override - public void setup() { + public void setup(VaadinRequest request) { TextField tf = new TextField("test", "testing"); tf.setWidth("100%"); @@ -30,15 +30,12 @@ public class TextFieldRelativeWidth extends TestBase { private Button addButton = new Button("Add new row", this); private String inputPrompt; - private String inputPromptChild; - private int nextItemIndex = 1; - private static final long serialVersionUID = 3326806911297977454L; - + @SuppressWarnings("unchecked") public EditTable() { - setColumnHeaderMode(Table.COLUMN_HEADER_MODE_HIDDEN); + setColumnHeaderMode(ColumnHeaderMode.HIDDEN); inputPrompt = ""; setPageLength(100); setHeight("100%"); @@ -51,20 +48,9 @@ public class TextFieldRelativeWidth extends TestBase { i.getItemProperty("text").setValue(addButton); setImmediate(true); setSelectable(true); - addListener(new Property.ValueChangeListener() { - private static final long serialVersionUID = 448896474865195605L; - - @Override - public void valueChange( - com.vaadin.data.Property.ValueChangeEvent event) { - // IndexedContainer idc = (IndexedContainer) - // getContainerDataSource(); - - } - - }); } + @SuppressWarnings("unchecked") public void addNewRow() { IndexedContainer idc = (IndexedContainer) getContainerDataSource(); int size = idc.size(); @@ -87,8 +73,6 @@ public class TextFieldRelativeWidth extends TestBase { if (inputPromptChild != null && inputPromptChild.length() > 0) { tf.setInputPrompt(inputPromptChild); } - // tf.setRows(1); - // tf.setHeight("45px"); tf.setWidth("100%"); tf.addStyleName("childtf"); newItem.getItemProperty("text").setValue(tf); @@ -119,7 +103,7 @@ public class TextFieldRelativeWidth extends TestBase { } @Override - protected String getDescription() { + protected String getTestDescription() { return "The table has 3 columns. The second column is expanded and contains 100% wide textfields. These should fill the available space. The third column is empty."; } diff --git a/uitest/src/com/vaadin/tests/components/table/TextFieldRelativeWidthTest.java b/uitest/src/com/vaadin/tests/components/table/TextFieldRelativeWidthTest.java new file mode 100644 index 0000000000..520ffa1aec --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/TextFieldRelativeWidthTest.java @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2014 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.table; + +import java.io.IOException; + +import org.junit.Test; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Tests that a TextField with 100% width fills the expanded column. + * + * @author Vaadin Ltd + */ +public class TextFieldRelativeWidthTest extends MultiBrowserTest { + + @Test + public void testWidth() throws IOException { + openTestURL(); + + compareScreen("initial"); + + ButtonElement button = $(ButtonElement.class).first(); + button.click(); + button.click(); + + compareScreen("after"); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/TabKeyboardNavigation.html b/uitest/src/com/vaadin/tests/components/tabsheet/TabKeyboardNavigation.html deleted file mode 100644 index 825988173a..0000000000 --- a/uitest/src/com/vaadin/tests/components/tabsheet/TabKeyboardNavigation.html +++ /dev/null @@ -1,241 +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" /> -<title>TabKeyboardNavigation</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">TabKeyboardNavigation</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/TabKeyboardNavigation?restartApplication</td> - <td></td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td> - <td>9,8</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td> - <td>right</td> -</tr> -<tr> - <td>pause</td> - <td>1000</td> - <td>1000</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[1]/ChildComponentContainer[0]/VLabel[0]</td> - <td>Tab 1</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td> - <td>space</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[1]/ChildComponentContainer[0]/VLabel[0]</td> - <td>Tab 2</td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td>tab2</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[1]</td> - <td>right</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[2]</td> - <td>right</td> -</tr> -<tr> - <td>pause</td> - <td>1000</td> - <td>1000</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[3]/ChildComponentContainer[0]/VLabel[0]</td> - <td>Tab 2</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[2]</td> - <td>space</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[3]/ChildComponentContainer[0]/VLabel[0]</td> - <td>Tab 5</td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td>skip-disabled-to-tab5</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td> - <td>right</td> -</tr> -<tr> - <td>pause</td> - <td>1000</td> - <td>1000</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[4]/ChildComponentContainer[0]/VLabel[0]</td> - <td>Tab 5</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td> - <td>space</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[4]/ChildComponentContainer[0]/VLabel[0]</td> - <td>Tab 6</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[8]/domChild[0]/domChild[0]/domChild[0]</td> - <td>18,10</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[8]</td> - <td>right</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[9]</td> - <td>right</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[10]</td> - <td>right</td> -</tr> -<tr> - <td>pause</td> - <td>1000</td> - <td>1000</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[8]/ChildComponentContainer[0]/VLabel[0]</td> - <td>Tab 9</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[10]</td> - <td>space</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[8]/ChildComponentContainer[0]/VLabel[0]</td> - <td>Tab 12</td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td>scrolled-right-to-tab-12</td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[4]/domChild[0]/domChild[0]/domChild[0]</td> - <td>11,2</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[4]</td> - <td>left</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[2]</td> - <td>left</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[1]</td> - <td>left</td> -</tr> -<tr> - <td>pause</td> - <td>1000</td> - <td>1000</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td> - <td>Tab 5</td> -</tr> -<tr> - <td>pressSpecialKey</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[1]</td> - <td>space</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td> - <td>Tab 1</td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td>scrolled-left-to-tab-1</td> -</tr> - -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/TabKeyboardNavigation.java b/uitest/src/com/vaadin/tests/components/tabsheet/TabKeyboardNavigation.java index ba737f1df8..620f04fe60 100644 --- a/uitest/src/com/vaadin/tests/components/tabsheet/TabKeyboardNavigation.java +++ b/uitest/src/com/vaadin/tests/components/tabsheet/TabKeyboardNavigation.java @@ -6,7 +6,8 @@ import com.vaadin.event.FieldEvents.BlurEvent; import com.vaadin.event.FieldEvents.BlurListener; import com.vaadin.event.FieldEvents.FocusEvent; import com.vaadin.event.FieldEvents.FocusListener; -import com.vaadin.tests.components.TestBase; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.tests.util.Log; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; @@ -19,7 +20,16 @@ import com.vaadin.ui.TabSheet.Tab; import com.vaadin.ui.TextField; import com.vaadin.ui.VerticalLayout; -public class TabKeyboardNavigation extends TestBase { +/** + * Test if the click and key tab selection in a tabsheet generate the correct + * focus/blur events. + * + * The solution was broken in ticket (#14304) + * + * @since + * @author Vaadin Ltd + */ +public class TabKeyboardNavigation extends AbstractTestUI { int index = 1; ArrayList<Component> tabs = new ArrayList<Component>(); @@ -27,18 +37,18 @@ public class TabKeyboardNavigation extends TestBase { Log focusblur = new Log(10); @Override - protected void setup() { + protected void setup(VaadinRequest request) { ts.setWidth("500px"); ts.setHeight("500px"); - ts.addListener(new FocusListener() { + ts.addFocusListener(new FocusListener() { @Override public void focus(FocusEvent event) { focusblur.log("Tabsheet focused!"); } }); - ts.addListener(new BlurListener() { + ts.addBlurListener(new BlurListener() { @Override public void blur(BlurEvent event) { focusblur.log("Tabsheet blurred!"); @@ -74,7 +84,7 @@ public class TabKeyboardNavigation extends TestBase { } @Override - protected String getDescription() { + protected String getTestDescription() { return "The tab bar should be focusable and arrow keys should switch tabs. The del key should close a tab if closable."; } @@ -83,10 +93,18 @@ public class TabKeyboardNavigation extends TestBase { return 5100; } + public final static String LABEL_ID = "sheetLabel"; + + public final static String labelID(int index) { + return LABEL_ID + index; + } + private Tab addTab() { Layout content = new VerticalLayout(); tabs.add(content); - content.addComponent(new Label("Tab " + index)); + Label label = new Label("Tab " + index); + label.setId(labelID(index)); + content.addComponent(label); content.addComponent(new TextField()); Tab tab = ts.addTab(content, "Tab " + index, null); if (index == 2) { diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/TabKeyboardNavigationTest.java b/uitest/src/com/vaadin/tests/components/tabsheet/TabKeyboardNavigationTest.java new file mode 100644 index 0000000000..65307f9492 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/tabsheet/TabKeyboardNavigationTest.java @@ -0,0 +1,188 @@ +/* + * Copyright 2000-2014 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.tabsheet; + +import java.io.IOException; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Add TB3 test as the TB2 one failed on keyboard events. + * + * @since + * @author Vaadin Ltd + */ +public class TabKeyboardNavigationTest extends MultiBrowserTest { + + @Test + public void testFocus() throws InterruptedException, IOException { + openTestURL(); + + click(1); + sendKeys(1, Keys.ARROW_RIGHT); + + assertSheet(1); + sendKeys(2, Keys.SPACE); + assertSheet(2); + compareScreen("tab2"); + + sendKeys(2, Keys.ARROW_RIGHT); + sendKeys(3, Keys.ARROW_RIGHT); + assertSheet(2); + + sendKeys(5, Keys.SPACE); + assertSheet(5); + compareScreen("skip-disabled-to-tab5"); + + TestBenchElement addTabButton = (TestBenchElement) getDriver() + .findElements(By.className("v-button")).get(0); + + click(addTabButton); + + click(5); + sendKeys(5, Keys.ARROW_RIGHT); + assertSheet(5); + + sendKeys(6, Keys.SPACE); + assertSheet(6); + + click(addTabButton); + click(addTabButton); + click(addTabButton); + click(addTabButton); + click(addTabButton); + click(addTabButton); + + click(8); + compareScreen("click-tab-8"); + + sendKeys(8, Keys.ARROW_RIGHT); + sendKeys(9, Keys.SPACE); + click(9); + compareScreen("tab-9"); + + sendKeys(9, Keys.ARROW_RIGHT); + Thread.sleep(DELAY); + + sendKeys(10, Keys.ARROW_RIGHT); + + // Here PhantomJS used to fail. Or when accessing tab2. The fix was to + // call the elem.click(x, y) using the (x, y) position instead of the + // elem.click() without any arguments. + sendKeys(11, Keys.ARROW_RIGHT); + + assertSheet(9); + sendKeys(12, Keys.SPACE); + assertSheet(12); + compareScreen("scrolled-right-to-tab-12"); + + click(5); + + sendKeys(5, Keys.ARROW_LEFT); + + // Here IE8 used to fail. A hidden <div> in IE8 would have the bounds of + // it's parent, and when trying to see in which direction to scroll + // (left or right) to make the key selected tab visible, the + // VTabSheet.scrollIntoView(Tab) used to check first whether the tab + // isClipped. On IE8 this will always return true for both hidden tabs + // on the left and clipped tabs on the right. So instead of going to + // left, it'll search all the way to the right. + sendKeys(3, Keys.ARROW_LEFT); + sendKeys(2, Keys.ARROW_LEFT); + assertSheet(5); + + sendKeys(1, Keys.SPACE); + assertSheet(1); + compareScreen("scrolled-left-to-tab-1"); + } + + /* + * Press key on the element. + */ + private void sendKeys(int tabIndex, Keys key) throws InterruptedException { + sendKeys(tab(tabIndex), key); + } + + /* + * Press key on the element. + */ + private void sendKeys(TestBenchElement element, Keys key) + throws InterruptedException { + + element.sendKeys(key); + if (DELAY > 0) { + sleep(DELAY); + } + } + + /* + * Click on the element. + */ + private void click(int tabIndex) throws InterruptedException { + click(tab(tabIndex)); + } + + /* + * Click on the element. + */ + private void click(TestBenchElement element) throws InterruptedException { + + element.click(10, 10); + if (DELAY > 0) { + sleep(DELAY); + } + } + + /* + * Delay for PhantomJS. + */ + private final static int DELAY = 10; + + private void assertSheet(int index) { + String labelCaption = "Tab " + index; + + By id = By.id(TabKeyboardNavigation.labelID(index)); + WebElement labelElement = getDriver().findElement(id); + + waitForElementPresent(id); + + Assert.assertEquals(labelCaption, labelCaption, labelElement.getText()); + } + + /* + * Provide the tab at specified index. + */ + private TestBenchElement tab(int index) { + By by = By.className("v-tabsheet-tabitemcell"); + + TestBenchElement element = (TestBenchElement) getDriver().findElements( + by).get(index - 1); + + String expected = "Tab " + index; + Assert.assertEquals(expected, + element.getText().substring(0, expected.length())); + + return element; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/TabSpaceNotScroll.java b/uitest/src/com/vaadin/tests/components/tabsheet/TabSpaceNotScroll.java new file mode 100644 index 0000000000..3a5be51e47 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/tabsheet/TabSpaceNotScroll.java @@ -0,0 +1,67 @@ +/* + * Copyright 2000-2014 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.tabsheet; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Alignment; +import com.vaadin.ui.Component; +import com.vaadin.ui.Label; +import com.vaadin.ui.TabSheet; +import com.vaadin.ui.VerticalLayout; + +/** + * If the space is pressed on the tabs of a tabsheet the browser default scroll + * behavior must be prevented. + * + * @since + * @author Vaadin Ltd + */ +public class TabSpaceNotScroll extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + TabSheet tabSheet = new TabSheet(); + + for (int i = 0; i < 5; i++) { + String caption = "Tab " + i; + Component c = new Label(caption); + tabSheet.addTab(c, caption); + } + + addComponent(tabSheet); + + Label dontShowThis = new Label("Page scroll. This is bad."); + + VerticalLayout panel = new VerticalLayout(); + panel.setHeight("2000px"); + panel.addComponent(dontShowThis); + panel.setComponentAlignment(dontShowThis, Alignment.MIDDLE_CENTER); + + addComponent(panel); + } + + @Override + protected String getTestDescription() { + return "Pressing space on the tab should not scroll."; + } + + @Override + protected Integer getTicketNumber() { + return 14320; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/TabSpaceNotScrollTest.java b/uitest/src/com/vaadin/tests/components/tabsheet/TabSpaceNotScrollTest.java new file mode 100644 index 0000000000..c35248c1f4 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/tabsheet/TabSpaceNotScrollTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2014 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.tabsheet; + +import java.io.IOException; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.Point; + +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Test if the page scroll when press space on a tabsheet's tab. + * + * @since + * @author Vaadin Ltd + */ +public class TabSpaceNotScrollTest extends MultiBrowserTest { + + @Test + public void testScroll() throws InterruptedException, IOException { + openTestURL(); + + TestBenchElement tab = (TestBenchElement) getDriver().findElement( + By.className("v-tabsheet-tabitemcell")); + tab.click(10, 10); + + Point oldLocation = tab.getLocation(); + + tab.sendKeys(Keys.SPACE); + + Point newLocation = tab.getLocation(); + + Assert.assertEquals(oldLocation, newLocation); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/treetable/TreeTablePartialUpdatesPageLength0.html b/uitest/src/com/vaadin/tests/components/treetable/TreeTablePartialUpdatesPageLength0.html deleted file mode 100644 index 34ab0c0c2e..0000000000 --- a/uitest/src/com/vaadin/tests/components/treetable/TreeTablePartialUpdatesPageLength0.html +++ /dev/null @@ -1,56 +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>DisappearingComponents</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">DisappearingComponents</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.components.treetable.TreeTablePartialUpdatesPageLength0?restartApplication</td> - <td></td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestscomponentstreetableTreeTablePartialUpdatesPageLength0::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td> - <td>10,2</td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td>root1-expanded-10-items</td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestscomponentstreetableTreeTablePartialUpdatesPageLength0::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[12]/domChild[0]/domChild[0]/domChild[0]</td> - <td>11,3</td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestscomponentstreetableTreeTablePartialUpdatesPageLength0::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[11]/domChild[0]/domChild[0]/domChild[0]</td> - <td>9,7</td> -</tr> -<tr> - <td>scroll</td> - <td>vaadin=runcomvaadintestscomponentstreetableTreeTablePartialUpdatesPageLength0::</td> - <td>12500</td> -</tr> -<tr> - <td>pause</td> - <td>300</td> - <td></td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td>all-expanded-bottom</td> -</tr> -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/components/treetable/TreeTablePartialUpdatesPageLength0.java b/uitest/src/com/vaadin/tests/components/treetable/TreeTablePartialUpdatesPageLength0.java index 20412bf0e2..686d86a0dc 100644 --- a/uitest/src/com/vaadin/tests/components/treetable/TreeTablePartialUpdatesPageLength0.java +++ b/uitest/src/com/vaadin/tests/components/treetable/TreeTablePartialUpdatesPageLength0.java @@ -2,13 +2,14 @@ package com.vaadin.tests.components.treetable; import com.vaadin.data.Container.Hierarchical; import com.vaadin.data.util.HierarchicalContainer; -import com.vaadin.tests.components.TestBase; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.ui.TreeTable; -public class TreeTablePartialUpdatesPageLength0 extends TestBase { +public class TreeTablePartialUpdatesPageLength0 extends AbstractTestUI { @Override - protected void setup() { + protected void setup(VaadinRequest request) { setTheme("reindeer-tests"); TreeTable tt = new TreeTable(); tt.addStyleName("table-equal-rowheight"); @@ -20,6 +21,7 @@ public class TreeTablePartialUpdatesPageLength0 extends TestBase { tt.getParent().getParent().setHeight(null); } + @SuppressWarnings("unchecked") private Hierarchical makeHierarchicalContainer() { HierarchicalContainer hc = new HierarchicalContainer(); hc.addContainerProperty("p1", String.class, ""); @@ -47,6 +49,7 @@ public class TreeTablePartialUpdatesPageLength0 extends TestBase { return hc; } + @SuppressWarnings("unchecked") private void addNodesToRoot(HierarchicalContainer hc, Object root, int count) { for (int ix = 0; ix < count; ix++) { Object id = hc.addItem(); @@ -56,7 +59,7 @@ public class TreeTablePartialUpdatesPageLength0 extends TestBase { } @Override - protected String getDescription() { + protected String getTestDescription() { return ""; } diff --git a/uitest/src/com/vaadin/tests/components/treetable/TreeTablePartialUpdatesPageLength0Test.java b/uitest/src/com/vaadin/tests/components/treetable/TreeTablePartialUpdatesPageLength0Test.java new file mode 100644 index 0000000000..d88c6ba7ca --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/treetable/TreeTablePartialUpdatesPageLength0Test.java @@ -0,0 +1,86 @@ +/* + * Copyright 2000-2014 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.treetable; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.By; +import com.vaadin.testbench.elements.TreeTableElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Tests expanding TreeTable rows when page length is zero. + * + * @author Vaadin Ltd + */ +public class TreeTablePartialUpdatesPageLength0Test extends MultiBrowserTest { + + @Test + public void testExpanding() throws IOException { + openTestURL(); + + TreeTableElement treeTable = $(TreeTableElement.class).first(); + List<WebElement> rows = treeTable.findElement( + By.className("v-table-body")).findElements(By.tagName("tr")); + assertEquals("unexpected row count", 4, rows.size()); + assertEquals("unexpected contents", "root1", treeTable.getCell(0, 0) + .getText()); + assertEquals("unexpected contents", "root2", treeTable.getCell(1, 0) + .getText()); + assertEquals("unexpected contents", "root3", treeTable.getCell(2, 0) + .getText()); + assertEquals("unexpected contents", "END", treeTable.getCell(3, 0) + .getText()); + + // expand first row, should have 10 children + treeTable.getCell(0, 0) + .findElement(By.className("v-treetable-treespacer")).click(); + + treeTable = $(TreeTableElement.class).first(); + rows = treeTable.findElement(By.className("v-table-body")) + .findElements(By.tagName("tr")); + assertEquals("unexpected row count", 14, rows.size()); + + // expand root3, should have 200 children + assertEquals("unexpected contents", "root3", treeTable.getCell(12, 0) + .getText()); + treeTable.getCell(12, 0) + .findElement(By.className("v-treetable-treespacer")).click(); + + // expand root2, should have 200 children + assertEquals("unexpected contents", "root2", treeTable.getCell(11, 0) + .getText()); + treeTable.getCell(11, 0) + .findElement(By.className("v-treetable-treespacer")).click(); + + treeTable = $(TreeTableElement.class).first(); + rows = treeTable.findElement(By.className("v-table-body")) + .findElements(By.tagName("tr")); + assertEquals("unexpected row count", 414, rows.size()); + + // scroll all the way to the bottom + WebElement ui = findElement(By.className("v-ui")); + testBenchElement(ui).scroll(12500); + + compareScreen("bottom"); + } +} diff --git a/uitest/src/com/vaadin/tests/components/window/ComboboxScrollableWindowTest.java b/uitest/src/com/vaadin/tests/components/window/ComboboxScrollableWindowTest.java index e65a24e907..627efdc5b3 100644 --- a/uitest/src/com/vaadin/tests/components/window/ComboboxScrollableWindowTest.java +++ b/uitest/src/com/vaadin/tests/components/window/ComboboxScrollableWindowTest.java @@ -35,8 +35,6 @@ public class ComboboxScrollableWindowTest extends MultiBrowserTest { @Test public void testWindowScrollbars() throws Exception { openTestURL(); - com.vaadin.testbench.Parameters - .setScreenshotComparisonCursorDetection(true); WebElement window = driver.findElement(By.id(WINDOW_ID)); WebElement scrollableElement = window.findElement(By diff --git a/uitest/src/com/vaadin/tests/components/window/ExtraWindowShownWaiAria.html b/uitest/src/com/vaadin/tests/components/window/ExtraWindowShownWaiAria.html deleted file mode 100644 index f5f89d13ef..0000000000 --- a/uitest/src/com/vaadin/tests/components/window/ExtraWindowShownWaiAria.html +++ /dev/null @@ -1,136 +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>ExtraWindowShownWaiAria</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">ExtraWindowShownWaiAria</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.components.window.ExtraWindowShownWaiAria?restartApplication</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>assertElementPresent</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/</td> - <td></td> -</tr> -<tr> - <td>assertAttribute</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/@role</td> - <td>dialog</td> -</tr> -<tr> - <td>storeAttribute</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/domChild[0]/domChild[0]/domChild[1]/domChild[0]@id</td> - <td>headerid</td> -</tr> -<tr> - <td>assertAttribute</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/@aria-labelledby</td> - <td>${headerid}</td> -</tr> -<tr> - <td>storeAttribute</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/FocusableScrollPanel[0]/VCssLayout[0]/VLabel[0]@id</td> - <td>descriptionid</td> -</tr> -<tr> - <td>assertAttribute</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/@aria-describedby</td> - <td>${descriptionid}</td> -</tr> -<tr> - <td>assertAttribute</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/domChild[0]/domChild[0]/domChild[2]@role</td> - <td>button</td> -</tr> -<tr> - <td>assertAttribute</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/domChild[0]/domChild[0]/domChild[3]@role</td> - <td>button</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/FocusableScrollPanel[0]/VCssLayout[0]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>assertElementNotPresent</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VCheckBox[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>storeAttribute</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/FocusableScrollPanel[0]/VCssLayout[0]/VLabel[0]@id</td> - <td>descriptionid</td> -</tr> -<tr> - <td>storeAttribute</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/FocusableScrollPanel[0]/VCssLayout[0]/VLabel[1]@id</td> - <td>description2id</td> -</tr> -<tr> - <td>assertAttribute</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/@aria-describedby</td> - <td>${descriptionid} ${description2id}</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/FocusableScrollPanel[0]/VCssLayout[0]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>assertElementNotPresent</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/</td> - <td></td> -</tr> -<tr> - <td>type</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[6]/VTextField[0]</td> - <td>Important</td> -</tr> -<tr> - <td>type</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[7]/VTextField[0]</td> - <td> - do ASAP</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>xpath=//div[@class='v-window-header']/span[@class='v-assistive-device-only'][1]</td> - <td>Important</td> -</tr> -<tr> - <td>assertText</td> - <td>xpath=//div[@class='v-window-header']/span[@class='v-assistive-device-only'][2]</td> - <td>- do ASAP</td> -</tr> -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/components/window/ExtraWindowShownWaiAriaTest.java b/uitest/src/com/vaadin/tests/components/window/ExtraWindowShownWaiAriaTest.java new file mode 100644 index 0000000000..44aea3522a --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/window/ExtraWindowShownWaiAriaTest.java @@ -0,0 +1,128 @@ +/* + * Copyright 2000-2014 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.window; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.CheckBoxElement; +import com.vaadin.testbench.elements.TextFieldElement; +import com.vaadin.testbench.elements.WindowElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Tests dialogs with WAI-ARIA. + * + * @since + * @author Vaadin Ltd + */ +public class ExtraWindowShownWaiAriaTest extends MultiBrowserTest { + + @Test + public void testDialogs() throws InterruptedException { + openTestURL(); + + List<ButtonElement> buttons = $(ButtonElement.class).all(); + assertFalse(buttons.isEmpty()); + + // open alert dialog + buttons.get(0).click(); + + // ensure dialog opened + List<WindowElement> windows = $(WindowElement.class).all(); + assertFalse(windows.isEmpty()); + + // ensure correct attributes + assertEquals("alertdialog", windows.get(0).getAttribute("role")); + + WebElement header = windows.get(0).findElement( + By.className("v-window-header")); + assertEquals(header.getAttribute("id"), + windows.get(0).getAttribute("aria-labelledby")); + + WebElement label = windows.get(0).findElement(By.className("v-label")); + assertEquals(label.getAttribute("id"), + windows.get(0).getAttribute("aria-describedby")); + + List<WebElement> wButtons = windows.get(0).findElements( + By.className("v-button")); + assertEquals("button", wButtons.get(0).getAttribute("role")); + assertEquals("button", wButtons.get(1).getAttribute("role")); + + // close dialog + wButtons.get(0).click(); + + // ensure dialog closed + windows = $(WindowElement.class).all(); + assertTrue(windows.isEmpty()); + + // check additional description (second checkbox on the page) + List<CheckBoxElement> checkBoxes = $(CheckBoxElement.class).all(); + WebElement input = checkBoxes.get(1).findElement(By.tagName("input")); + // ensure that not checked yet + assertEquals(null, input.getAttribute("checked")); + input.click(); + // ensure that checked now + assertEquals("true", input.getAttribute("checked")); + + // open alert dialog + buttons = $(ButtonElement.class).all(); + buttons.get(0).click(); + + // ensure correct attributes + windows = $(WindowElement.class).all(); + List<WebElement> labels = windows.get(0).findElements( + By.className("v-label")); + assertEquals(labels.get(0).getAttribute("id") + " " + + labels.get(1).getAttribute("id"), windows.get(0) + .getAttribute("aria-describedby")); + + // close dialog + wButtons = windows.get(0).findElements(By.className("v-button")); + wButtons.get(0).click(); + + // ensure dialog closed + windows = $(WindowElement.class).all(); + assertTrue(windows.isEmpty()); + + // add prefix and postfix + List<TextFieldElement> textFields = $(TextFieldElement.class).all(); + textFields.get(0).sendKeys("Important"); + textFields.get(1).sendKeys(" - do ASAP"); + + // open alert dialog + buttons = $(ButtonElement.class).all(); + buttons.get(0).click(); + + // ensure the assistive spans have been added to the header + windows = $(WindowElement.class).all(); + header = windows.get(0).findElement(By.className("v-window-header")); + List<WebElement> assistiveElements = header.findElements(By + .className("v-assistive-device-only")); + assertEquals("Important", + assistiveElements.get(0).getAttribute("innerHTML")); + assertEquals(" - do ASAP", + assistiveElements.get(1).getAttribute("innerHTML")); + } +} diff --git a/uitest/src/com/vaadin/tests/components/window/TestTooSmallSubwindowSize.html b/uitest/src/com/vaadin/tests/components/window/TestTooSmallSubwindowSize.html deleted file mode 100644 index f926696d63..0000000000 --- a/uitest/src/com/vaadin/tests/components/window/TestTooSmallSubwindowSize.html +++ /dev/null @@ -1,32 +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>TestTooSmallSubwindowSize</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">TestTooSmallSubwindowSize</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.components.window.TestTooSmallSubwindowSize</td> - <td></td> -</tr> -<tr> - <td>waitForVaadin</td> - <td></td> - <td></td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td></td> -</tr> - -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/components/window/TestTooSmallSubwindowSize.java b/uitest/src/com/vaadin/tests/components/window/TestTooSmallSubwindowSize.java index 46845748a3..669774f715 100644 --- a/uitest/src/com/vaadin/tests/components/window/TestTooSmallSubwindowSize.java +++ b/uitest/src/com/vaadin/tests/components/window/TestTooSmallSubwindowSize.java @@ -1,15 +1,22 @@ package com.vaadin.tests.components.window; -import com.vaadin.tests.components.TestBase; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.ui.Label; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; -public class TestTooSmallSubwindowSize extends TestBase { +/** + * Tests that the styles work correctly in tiny subwindows that have more + * content than can fit. + * + * @author Vaadin Ltd + */ +public class TestTooSmallSubwindowSize extends AbstractTestUI { @Override - protected String getDescription() { - return "The size of the subwindow (outer size) is set to 60x60 pixels. Minimum size for the content area is 150x100, which means the window and shadow should be around 155x155 and the content area 150x100. The decoration at the lower left corner of the window must not be missing either."; + protected String getTestDescription() { + return "The size of the subwindows (outer size) is set to 60x60 pixels. Make sure the shadows fits the windows instead of the contents. The decorations at the lower right corners of the resizable windows must not be missing either."; } @Override @@ -18,7 +25,14 @@ public class TestTooSmallSubwindowSize extends TestBase { } @Override - protected void setup() { + protected void setup(VaadinRequest request) { + getUI().addWindow(createNonResizableWindow()); + getUI().addWindow(createNonResizableWindowWithHorizontalScrollbar()); + getUI().addWindow(createResizableWindow()); + getUI().addWindow(createResizableWindowWithHorizontalScrollbar()); + } + + private Window createNonResizableWindow() { VerticalLayout layout = new VerticalLayout(); layout.setMargin(true); Window w = new Window("Scroll", layout); @@ -35,13 +49,94 @@ public class TestTooSmallSubwindowSize extends TestBase { w.setPositionY(100); // Set window size - w.setWidth(60, Window.UNITS_PIXELS); - w.setHeight(60, Window.UNITS_PIXELS); + w.setWidth(60, Unit.PIXELS); + w.setHeight(60, Unit.PIXELS); + + // Disable resizing + w.setResizable(false); + + return w; + } + + private Window createNonResizableWindowWithHorizontalScrollbar() { + VerticalLayout layout = new VerticalLayout(); + layout.setMargin(true); + Window w = new Window("Scroll", layout); + Label desc = new Label( + "This is a new child window with a preset" + + " width, height and position. Resizing has been" + + " disabled for this window. Additionally, this text label" + + " is intentionally too large to fit the window. You could" + + " use the scrollbars to view different parts of the window content," + + " except it's too small for that either."); + // disable wrapping + desc.setSizeUndefined(); + layout.addComponent(desc); + + // Set window position + w.setPositionX(200); + w.setPositionY(100); + + // Set window size + w.setWidth(60, Unit.PIXELS); + w.setHeight(60, Unit.PIXELS); // Disable resizing - w.setResizable(true); + w.setResizable(false); + + return w; + } + + private Window createResizableWindow() { + VerticalLayout layout = new VerticalLayout(); + layout.setMargin(true); + Window w = new Window("Resize", layout); + Label desc = new Label( + "This is a new child window with a preset" + + " width, height and position. Resizing has not been" + + " disabled for this window. Additionally, this text label" + + " is intentionally too large to fit the window. You can resize or" + + " use the scrollbars to view different parts of the window content."); + layout.addComponent(desc); + + // Set window position + w.setPositionX(300); + w.setPositionY(100); + + // Set window size + w.setWidth(60, Unit.PIXELS); + w.setHeight(60, Unit.PIXELS); + + // Don't disable resizing + + return w; + } + + private Window createResizableWindowWithHorizontalScrollbar() { + VerticalLayout layout = new VerticalLayout(); + layout.setMargin(true); + Window w = new Window("Resize", layout); + Label desc = new Label( + "This is a new child window with a preset" + + " width, height and position. Resizing has not been" + + " disabled for this window. Additionally, this text label" + + " is intentionally too large to fit the window. You can resize" + + " to view different parts of the window content."); + // disable wrapping + desc.setSizeUndefined(); + layout.addComponent(desc); + + // Set window position + w.setPositionX(400); + w.setPositionY(100); + + // Set window size + w.setWidth(60, Unit.PIXELS); + w.setHeight(60, Unit.PIXELS); + + // Don't disable resizing - getMainWindow().addWindow(w); + return w; } } diff --git a/uitest/src/com/vaadin/tests/components/window/TestTooSmallSubwindowSizeTest.java b/uitest/src/com/vaadin/tests/components/window/TestTooSmallSubwindowSizeTest.java new file mode 100644 index 0000000000..0019900884 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/window/TestTooSmallSubwindowSizeTest.java @@ -0,0 +1,38 @@ +/* + * Copyright 2000-2014 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.window; + +import java.io.IOException; + +import org.junit.Test; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Tests that the styles work correctly in tiny subwindows that have more + * content than can fit. + * + * @author Vaadin Ltd + */ +public class TestTooSmallSubwindowSizeTest extends MultiBrowserTest { + + @Test + public void testSubwindowStyles() throws IOException { + openTestURL(); + + compareScreen("initial"); + } +} diff --git a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java index e463f666d9..b892fbe4a0 100644 --- a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java +++ b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java @@ -18,14 +18,25 @@ package com.vaadin.tests.tb3; import static com.vaadin.tests.tb3.TB3Runner.localWebDriverIsUsed; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.lang.reflect.Field; import java.net.URL; import java.util.Collections; import java.util.List; +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpHost; +import org.apache.http.HttpResponse; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicHttpEntityEnclosingRequest; +import org.json.JSONException; +import org.json.JSONObject; import org.junit.After; import org.junit.Before; import org.junit.runner.RunWith; @@ -42,6 +53,7 @@ import org.openqa.selenium.interactions.internal.Coordinates; import org.openqa.selenium.internal.Locatable; import org.openqa.selenium.remote.BrowserType; import org.openqa.selenium.remote.DesiredCapabilities; +import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.ExpectedConditions; @@ -51,6 +63,7 @@ import com.thoughtworks.selenium.webdriven.WebDriverBackedSelenium; import com.vaadin.server.LegacyApplication; import com.vaadin.server.UIProvider; import com.vaadin.testbench.TestBench; +import com.vaadin.testbench.TestBenchDriverProxy; import com.vaadin.testbench.TestBenchElement; import com.vaadin.testbench.TestBenchTestCase; import com.vaadin.tests.components.AbstractTestUIWithLog; @@ -102,6 +115,11 @@ public abstract class AbstractTB3Test extends TestBenchTestCase { desiredCapabilities = Browser.FIREFOX.getDesiredCapabilities(); } + static { + com.vaadin.testbench.Parameters + .setScreenshotComparisonCursorDetection(true); + } + /** * Connect to the hub using a remote web driver, set the canvas size and * opens the initial URL as specified by {@link #getTestUrl()} @@ -233,6 +251,15 @@ public abstract class AbstractTB3Test extends TestBenchTestCase { */ private void setupRemoteDriver(DesiredCapabilities capabilities) throws Exception { + if (BrowserUtil.isIE(capabilities)) { + capabilities.setCapability( + InternetExplorerDriver.REQUIRE_WINDOW_FOCUS, + requireWindowFocusForIE()); + capabilities.setCapability( + InternetExplorerDriver.ENABLE_PERSISTENT_HOVERING, + usePersistentHoverForIE()); + } + for (int i = 1; i <= BROWSER_INIT_ATTEMPTS; i++) { try { WebDriver dr = TestBench.createDriver(new RemoteWebDriver( @@ -1128,4 +1155,93 @@ public abstract class AbstractTB3Test extends TestBenchTestCase { return findElement(By.xpath("//button[@title='Debug message log']")); } + /** + * Should the "require window focus" be enabled for Internet Explorer. + * RequireWindowFocus makes tests more stable but seems to be broken with + * certain commands such as sendKeys. Therefore it is not enabled by default + * for all tests + * + * @return true, to use the "require window focus" feature, false otherwise + */ + protected boolean requireWindowFocusForIE() { + return false; + } + + /** + * Should the "enable persistent hover" be enabled for Internet Explorer. + * + * Persistent hovering causes continuous firing of mouse over events at the + * last location the mouse cursor has been moved to. This is to avoid + * problems where the real mouse cursor is inside the browser window and + * Internet Explorer uses that location for some undefined operation + * (http:// + * jimevansmusic.blogspot.fi/2012/06/whats-wrong-with-internet-explorer + * .html) + * + * @return true, to use the "persistent hover" feature, false otherwise + */ + protected boolean usePersistentHoverForIE() { + return true; + } + + // FIXME: Remove this once TB4 getRemoteControlName works properly + private RemoteWebDriver getRemoteDriver() { + WebDriver d = getDriver(); + if (d instanceof TestBenchDriverProxy) { + try { + Field f = TestBenchDriverProxy.class + .getDeclaredField("actualDriver"); + f.setAccessible(true); + return (RemoteWebDriver) f.get(d); + } catch (Exception e) { + e.printStackTrace(); + } + } + + if (d instanceof RemoteWebDriver) { + return (RemoteWebDriver) d; + } + + return null; + + } + + // FIXME: Remove this once TB4 getRemoteControlName works properly + protected String getRemoteControlName() { + try { + RemoteWebDriver d = getRemoteDriver(); + if (d == null) { + return null; + } + HttpCommandExecutor ce = (HttpCommandExecutor) d + .getCommandExecutor(); + String hostName = ce.getAddressOfRemoteServer().getHost(); + int port = ce.getAddressOfRemoteServer().getPort(); + HttpHost host = new HttpHost(hostName, port); + DefaultHttpClient client = new DefaultHttpClient(); + URL sessionURL = new URL("http://" + hostName + ":" + port + + "/grid/api/testsession?session=" + d.getSessionId()); + BasicHttpEntityEnclosingRequest r = new BasicHttpEntityEnclosingRequest( + "POST", sessionURL.toExternalForm()); + HttpResponse response = client.execute(host, r); + JSONObject object = extractObject(response); + URL myURL = new URL(object.getString("proxyId")); + if ((myURL.getHost() != null) && (myURL.getPort() != -1)) { + return myURL.getHost(); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + private static JSONObject extractObject(HttpResponse resp) + throws IOException, JSONException { + InputStream contents = resp.getEntity().getContent(); + StringWriter writer = new StringWriter(); + IOUtils.copy(contents, writer, "UTF8"); + JSONObject objToReturn = new JSONObject(writer.toString()); + return objToReturn; + } + } diff --git a/uitest/src/com/vaadin/tests/themes/valo/ButtonsAndLinks.java b/uitest/src/com/vaadin/tests/themes/valo/ButtonsAndLinks.java index 758d2de200..e66cd2668b 100644 --- a/uitest/src/com/vaadin/tests/themes/valo/ButtonsAndLinks.java +++ b/uitest/src/com/vaadin/tests/themes/valo/ButtonsAndLinks.java @@ -136,6 +136,14 @@ public class ButtonsAndLinks extends VerticalLayout implements View { button = new Button("Three"); group.addComponent(button); + button = new Button("Tiny"); + button.addStyleName("tiny"); + row.addComponent(button); + + button = new Button("Huge"); + button.addStyleName("huge"); + row.addComponent(button); + NativeButton nbutton = new NativeButton("Native"); row.addComponent(nbutton); diff --git a/uitest/src/com/vaadin/tests/themes/valo/CalendarTest.java b/uitest/src/com/vaadin/tests/themes/valo/CalendarTest.java index 17dfd6cb67..280ddf98b7 100644 --- a/uitest/src/com/vaadin/tests/themes/valo/CalendarTest.java +++ b/uitest/src/com/vaadin/tests/themes/valo/CalendarTest.java @@ -4,7 +4,6 @@ import java.text.DateFormatSymbols; import java.util.Date; import java.util.GregorianCalendar; import java.util.Locale; -import java.util.Map; import java.util.TimeZone; import com.vaadin.annotations.Theme; @@ -51,6 +50,7 @@ import com.vaadin.ui.components.calendar.event.BasicEventProvider; import com.vaadin.ui.components.calendar.event.CalendarEvent; import com.vaadin.ui.components.calendar.handler.BasicDateClickHandler; import com.vaadin.ui.components.calendar.handler.BasicWeekClickHandler; +import com.vaadin.ui.themes.ValoTheme; /** Calendar component test application */ @Theme("valo-test") @@ -108,7 +108,7 @@ public class CalendarTest extends GridLayout implements View { private Button applyEventButton; - private Mode viewMode = Mode.MONTH; + private Mode viewMode = Mode.WEEK; private BasicEventProvider dataSource; @@ -152,52 +152,11 @@ public class CalendarTest extends GridLayout implements View { setSpacing(true); // handleURLParams(request.getParameterMap()); + testBench = ValoThemeUI.isTestMode(); initContent(); } - private void handleURLParams(Map<String, String[]> parameters) { - testBench = parameters.containsKey("testBench") - || parameters.containsKey("?testBench"); - - if (parameters.containsKey("width")) { - calendarWidth = parameters.get("width")[0]; - } - - if (parameters.containsKey("height")) { - calendarHeight = parameters.get("height")[0]; - } - - if (parameters.containsKey("firstDay")) { - firstDay = Integer.parseInt(parameters.get("firstDay")[0]); - } - - if (parameters.containsKey("lastDay")) { - lastDay = Integer.parseInt(parameters.get("lastDay")[0]); - } - - if (parameters.containsKey("firstHour")) { - firstHour = Integer.parseInt(parameters.get("firstHour")[0]); - } - - if (parameters.containsKey("lastHour")) { - lastHour = Integer.parseInt(parameters.get("lastHour")[0]); - } - - if (parameters.containsKey("locale")) { - String localeArray[] = parameters.get("locale")[0].split("_"); - defaultLocale = new Locale(localeArray[0], localeArray[1]); - setLocale(defaultLocale); - } - - if (parameters.containsKey(("secondsResolution"))) { - useSecondResolution = true; - } - - showWeeklyView = parameters.containsKey("weekly"); - - } - public void initContent() { // Set default Locale for this application if (testBench) { @@ -365,6 +324,9 @@ public class CalendarTest extends GridLayout implements View { Alignment.MIDDLE_LEFT); controlPanel.setComponentAlignment(addNewEvent, Alignment.MIDDLE_LEFT); + Label viewCaption = new Label("Calendar"); + viewCaption.setStyleName(ValoTheme.LABEL_H1); + addComponent(viewCaption); addComponent(controlPanel); addComponent(hl); addComponent(calendarComponent); @@ -645,6 +607,11 @@ public class CalendarTest extends GridLayout implements View { calendar.setTime(today); calendarComponent.getInternalCalendar().setTime(today); + // Calendar getStartDate (and getEndDate) has some strange logic which + // returns Monday of the current internal time if no start date has been + // set + calendarComponent.setStartDate(calendarComponent.getStartDate()); + calendarComponent.setEndDate(calendarComponent.getEndDate()); int rollAmount = calendar.get(GregorianCalendar.DAY_OF_MONTH) - 1; calendar.add(GregorianCalendar.DAY_OF_MONTH, -rollAmount); currentMonthsFirstDate = calendar.getTime(); diff --git a/uitest/src/com/vaadin/tests/themes/valo/ComboBoxes.java b/uitest/src/com/vaadin/tests/themes/valo/ComboBoxes.java index 1b8b290d91..98a9cad83c 100644 --- a/uitest/src/com/vaadin/tests/themes/valo/ComboBoxes.java +++ b/uitest/src/com/vaadin/tests/themes/valo/ComboBoxes.java @@ -162,6 +162,22 @@ public class ComboBoxes extends VerticalLayout implements View { combo.addItem("Option Three"); combo.addStyleName("borderless"); row.addComponent(combo); + + combo = new ComboBox("Tiny"); + combo.setInputPrompt("You can type here"); + combo.setContainerDataSource(ValoThemeUI.generateContainer(200, false)); + combo.setItemCaptionPropertyId(ValoThemeUI.CAPTION_PROPERTY); + combo.setItemIconPropertyId(ValoThemeUI.ICON_PROPERTY); + combo.addStyleName("tiny"); + row.addComponent(combo); + + combo = new ComboBox("Huge"); + combo.setInputPrompt("You can type here"); + combo.setContainerDataSource(ValoThemeUI.generateContainer(200, false)); + combo.setItemCaptionPropertyId(ValoThemeUI.CAPTION_PROPERTY); + combo.setItemIconPropertyId(ValoThemeUI.ICON_PROPERTY); + combo.addStyleName("huge"); + row.addComponent(combo); } @Override diff --git a/uitest/src/com/vaadin/tests/themes/valo/CommonParts.java b/uitest/src/com/vaadin/tests/themes/valo/CommonParts.java index cd378c3754..52cc43ac28 100644 --- a/uitest/src/com/vaadin/tests/themes/valo/CommonParts.java +++ b/uitest/src/com/vaadin/tests/themes/valo/CommonParts.java @@ -131,9 +131,11 @@ public class CommonParts extends VerticalLayout implements View { spinnerDesc.setCaption("Spinner"); content.addComponent(spinnerDesc); - Label spinner = new Label(); - spinner.addStyleName("spinner"); - content.addComponent(spinner); + if (!ValoThemeUI.isTestMode()) { + Label spinner = new Label(); + spinner.addStyleName("spinner"); + content.addComponent(spinner); + } return p; } diff --git a/uitest/src/com/vaadin/tests/themes/valo/DateFields.java b/uitest/src/com/vaadin/tests/themes/valo/DateFields.java index ae520e07c2..7738b2d6db 100644 --- a/uitest/src/com/vaadin/tests/themes/valo/DateFields.java +++ b/uitest/src/com/vaadin/tests/themes/valo/DateFields.java @@ -46,16 +46,16 @@ public class DateFields extends VerticalLayout implements View { addComponent(row); DateField date = new DateField("Default resolution"); - date.setValue(new Date()); + setDate(date); row.addComponent(date); date = new DateField("Error"); - date.setValue(new Date()); + setDate(date); date.setComponentError(new UserError("Fix it, now!")); row.addComponent(date); date = new DateField("Error, borderless"); - date.setValue(new Date()); + setDate(date); date.setComponentError(new UserError("Fix it, now!")); date.addStyleName("borderless"); row.addComponent(date); @@ -77,110 +77,132 @@ public class DateFields extends VerticalLayout implements View { group.addComponent(today); date = new DateField("Default resolution, explicit size"); - date.setValue(new Date()); + setDate(date); row.addComponent(date); date.setWidth("260px"); date.setHeight("60px"); date = new DateField("Second resolution"); - date.setValue(new Date()); + setDate(date); date.setResolution(Resolution.SECOND); row.addComponent(date); date = new DateField("Minute resolution"); - date.setValue(new Date()); + setDate(date); date.setResolution(Resolution.MINUTE); row.addComponent(date); date = new DateField("Hour resolution"); - date.setValue(new Date()); + setDate(date); date.setResolution(Resolution.HOUR); row.addComponent(date); date = new DateField("Disabled"); - date.setValue(new Date()); + setDate(date); date.setResolution(Resolution.HOUR); date.setEnabled(false); row.addComponent(date); date = new DateField("Day resolution"); - date.setValue(new Date()); + setDate(date); date.setResolution(Resolution.DAY); row.addComponent(date); date = new DateField("Month resolution"); - date.setValue(new Date()); + setDate(date); date.setResolution(Resolution.MONTH); row.addComponent(date); date = new DateField("Year resolution"); - date.setValue(new Date()); + setDate(date); date.setResolution(Resolution.YEAR); row.addComponent(date); date = new DateField("Custom color"); - date.setValue(new Date()); + setDate(date); date.setResolution(Resolution.DAY); date.addStyleName("color1"); row.addComponent(date); date = new DateField("Custom color"); - date.setValue(new Date()); + setDate(date); date.setResolution(Resolution.DAY); date.addStyleName("color2"); row.addComponent(date); date = new DateField("Custom color"); - date.setValue(new Date()); + setDate(date); date.setResolution(Resolution.DAY); date.addStyleName("color3"); row.addComponent(date); date = new DateField("Small"); - date.setValue(new Date()); + setDate(date); date.setResolution(Resolution.DAY); date.addStyleName("small"); row.addComponent(date); date = new DateField("Large"); - date.setValue(new Date()); + setDate(date); date.setResolution(Resolution.DAY); date.addStyleName("large"); row.addComponent(date); date = new DateField("Borderless"); - date.setValue(new Date()); + setDate(date); date.setResolution(Resolution.DAY); date.addStyleName("borderless"); row.addComponent(date); date = new DateField("Week numbers"); - date.setValue(new Date()); + setDate(date); date.setResolution(Resolution.DAY); date.setLocale(new Locale("fi", "fi")); date.setShowISOWeekNumbers(true); row.addComponent(date); date = new DateField("US locale"); - date.setValue(new Date()); + setDate(date); date.setResolution(Resolution.SECOND); date.setLocale(new Locale("en", "US")); row.addComponent(date); date = new DateField("Custom format"); - date.setValue(new Date()); + setDate(date); date.setDateFormat("E dd/MM/yyyy"); row.addComponent(date); + date = new DateField("Tiny"); + setDate(date); + date.setResolution(Resolution.DAY); + date.addStyleName("tiny"); + row.addComponent(date); + + date = new DateField("Huge"); + setDate(date); + date.setResolution(Resolution.DAY); + date.addStyleName("huge"); + row.addComponent(date); + date = new InlineDateField("Date picker"); + setDate(date); row.addComponent(date); date = new InlineDateField("Date picker with week numbers"); + setDate(date); date.setLocale(new Locale("fi", "fi")); date.setShowISOWeekNumbers(true); row.addComponent(date); } + private void setDate(DateField date) { + if (ValoThemeUI.isTestMode()) { + date.setValue(new Date(2014 - 1900, 5, 7)); + } else { + date.setValue(new Date()); + } + } + @Override public void enter(ViewChangeEvent event) { // TODO Auto-generated method stub diff --git a/uitest/src/com/vaadin/tests/themes/valo/Forms.java b/uitest/src/com/vaadin/tests/themes/valo/Forms.java index 6f1b8bbf7a..90a6c51496 100644 --- a/uitest/src/com/vaadin/tests/themes/valo/Forms.java +++ b/uitest/src/com/vaadin/tests/themes/valo/Forms.java @@ -47,7 +47,7 @@ public class Forms extends VerticalLayout implements View { setSpacing(true); setMargin(true); - Label title = new Label("Form"); + Label title = new Label("Forms"); title.addStyleName("h1"); addComponent(title); @@ -59,6 +59,7 @@ public class Forms extends VerticalLayout implements View { Label section = new Label("Personal Info"); section.addStyleName("h2"); + section.addStyleName("colored"); form.addComponent(section); StringGenerator sg = new StringGenerator(); @@ -85,6 +86,7 @@ public class Forms extends VerticalLayout implements View { section = new Label("Contact Info"); section.addStyleName("h3"); + section.addStyleName("colored"); form.addComponent(section); TextField email = new TextField("Email"); @@ -125,6 +127,7 @@ public class Forms extends VerticalLayout implements View { section = new Label("Additional Info"); section.addStyleName("h4"); + section.addStyleName("colored"); form.addComponent(section); TextField website = new TextField("Website"); diff --git a/uitest/src/com/vaadin/tests/themes/valo/Labels.java b/uitest/src/com/vaadin/tests/themes/valo/Labels.java index 08378ad9e6..b5bab3a1d3 100644 --- a/uitest/src/com/vaadin/tests/themes/valo/Labels.java +++ b/uitest/src/com/vaadin/tests/themes/valo/Labels.java @@ -45,6 +45,10 @@ public class Labels extends VerticalLayout implements View { left.setMargin(new MarginInfo(false, true, false, false)); split.addComponent(left); + Label huge = new Label("Huge type for display text."); + huge.addStyleName("huge"); + left.addComponent(huge); + Label large = new Label( "Large type for introductory text. Etiam at risus et justo dignissim congue. Donec congue lacinia dui, a porttitor lectus condimentum laoreet. Nunc eu."); large.addStyleName("large"); @@ -68,6 +72,10 @@ public class Labels extends VerticalLayout implements View { small.addStyleName("small"); left.addComponent(small); + Label tiny = new Label("Tiny type for minor text."); + tiny.addStyleName("tiny"); + left.addComponent(tiny); + Label h4 = new Label("Section Title"); h4.addStyleName("h4"); left.addComponent(h4); @@ -94,6 +102,11 @@ public class Labels extends VerticalLayout implements View { label.addStyleName("light"); right.addComponent(label); + label = new Label( + "Colored type for highlighted text. Etiam at risus et justo dignissim congue. Donec congue lacinia dui, a porttitor lectus condimentum laoreet. Nunc eu."); + label.addStyleName("colored"); + right.addComponent(label); + label = new Label("A label for success"); label.addStyleName("success"); right.addComponent(label); diff --git a/uitest/src/com/vaadin/tests/themes/valo/MenuBars.java b/uitest/src/com/vaadin/tests/themes/valo/MenuBars.java index 88eea73513..4a0130931e 100644 --- a/uitest/src/com/vaadin/tests/themes/valo/MenuBars.java +++ b/uitest/src/com/vaadin/tests/themes/valo/MenuBars.java @@ -18,6 +18,7 @@ package com.vaadin.tests.themes.valo; import com.vaadin.navigator.View; import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; import com.vaadin.server.FontAwesome; +import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.MenuBar; import com.vaadin.ui.MenuBar.Command; @@ -53,6 +54,62 @@ public class MenuBars extends VerticalLayout implements View { menuBar.addStyleName("borderless"); menuBar.addStyleName("small"); addComponent(menuBar); + + Label h2 = new Label("Drop Down Button"); + h2.addStyleName("h2"); + addComponent(h2); + + HorizontalLayout wrap = new HorizontalLayout(); + wrap.addStyleName("wrapping"); + wrap.setSpacing(true); + addComponent(wrap); + + wrap.addComponent(getMenuButton("Normal", false)); + + MenuBar split = getMenuButton("Small", false); + split.addStyleName("small"); + wrap.addComponent(split); + + split = getMenuButton("Borderless", false); + split.addStyleName("borderless"); + wrap.addComponent(split); + + split = getMenuButton("Themed", false); + split.addStyleName("color1"); + wrap.addComponent(split); + + split = getMenuButton("Small", false); + split.addStyleName("color1"); + split.addStyleName("small"); + wrap.addComponent(split); + + h2 = new Label("Split Button"); + h2.addStyleName("h2"); + addComponent(h2); + + wrap = new HorizontalLayout(); + wrap.addStyleName("wrapping"); + wrap.setSpacing(true); + addComponent(wrap); + + wrap.addComponent(getMenuButton("Normal", true)); + + split = getMenuButton("Small", true); + split.addStyleName("small"); + wrap.addComponent(split); + + split = getMenuButton("Borderless", true); + split.addStyleName("borderless"); + wrap.addComponent(split); + + split = getMenuButton("Themed", true); + split.addStyleName("color1"); + wrap.addComponent(split); + + split = getMenuButton("Small", true); + split.addStyleName("color1"); + split.addStyleName("small"); + wrap.addComponent(split); } static MenuBar getMenuBar() { @@ -180,6 +237,20 @@ public class MenuBars extends VerticalLayout implements View { return menubar; } + static MenuBar getMenuButton(String caption, boolean splitButton) { + MenuBar split = new MenuBar(); + MenuBar.MenuItem dropdown = split.addItem(caption, null); + if (splitButton) { + dropdown = split.addItem("", null); + } + dropdown.addItem("Another Action", null); + dropdown.addItem("Secondary Action", null); + dropdown.addSeparator(); + dropdown.addItem("Last Action", null); + + return split; + } + @Override public void enter(ViewChangeEvent event) { // TODO Auto-generated method stub diff --git a/uitest/src/com/vaadin/tests/themes/valo/Sliders.java b/uitest/src/com/vaadin/tests/themes/valo/Sliders.java index 363c698c32..8ed846e39f 100644 --- a/uitest/src/com/vaadin/tests/themes/valo/Sliders.java +++ b/uitest/src/com/vaadin/tests/themes/valo/Sliders.java @@ -158,11 +158,12 @@ public class Sliders extends VerticalLayout implements View { // pb2.setValue(0.6f); row.addComponent(pb2); - ProgressBar pb3 = new ProgressBar(); - pb3.setIndeterminate(true); - pb3.setCaption("Indeterminate"); - row.addComponent(pb3); - + if (!ValoThemeUI.isTestMode()) { + ProgressBar pb3 = new ProgressBar(); + pb3.setIndeterminate(true); + pb3.setCaption("Indeterminate"); + row.addComponent(pb3); + } } float progress = 0; @@ -196,14 +197,21 @@ public class Sliders extends VerticalLayout implements View { @Override public void enter(ViewChangeEvent event) { - getUI().setPollInterval(1000); - update.start(); + if (!ValoThemeUI.isTestMode()) { + getUI().setPollInterval(1000); + update.start(); + } else { + pb.setValue(0.3f); + pb2.setValue(0.6f); + } } @Override public void detach() { - getUI().setPollInterval(-1); - update.interrupt(); + if (!ValoThemeUI.isTestMode()) { + getUI().setPollInterval(-1); + update.interrupt(); + } super.detach(); } diff --git a/uitest/src/com/vaadin/tests/themes/valo/TextFields.java b/uitest/src/com/vaadin/tests/themes/valo/TextFields.java index f8606bb7c9..347a683673 100644 --- a/uitest/src/com/vaadin/tests/themes/valo/TextFields.java +++ b/uitest/src/com/vaadin/tests/themes/valo/TextFields.java @@ -182,6 +182,16 @@ public class TextFields extends VerticalLayout implements View { pwf.setIcon(FontAwesome.LOCK); row.addComponent(pwf); + tf = new TextField("Tiny"); + tf.setValue("Field value"); + tf.addStyleName("tiny"); + row.addComponent(tf); + + tf = new TextField("Huge"); + tf.setValue("Field value"); + tf.addStyleName("huge"); + row.addComponent(tf); + h1 = new Label("Text Areas"); h1.addStyleName("h1"); addComponent(h1); @@ -242,6 +252,16 @@ public class TextFields extends VerticalLayout implements View { ta.setValue("Field value, spanning multiple lines of text"); row.addComponent(ta); + ta = new TextArea("Tiny"); + ta.addStyleName("tiny"); + ta.setInputPrompt("Write your comment…"); + row.addComponent(ta); + + ta = new TextArea("Huge"); + ta.addStyleName("huge"); + ta.setInputPrompt("Write your comment…"); + row.addComponent(ta); + RichTextArea rta = new RichTextArea(); rta.setValue("<b>Some</b> <i>rich</i> content"); row.addComponent(rta); diff --git a/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUI.java b/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUI.java index 5f286989a0..501b5f573b 100644 --- a/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUI.java +++ b/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUI.java @@ -61,6 +61,8 @@ import com.vaadin.ui.themes.ValoTheme; @PreserveOnRefresh public class ValoThemeUI extends UI { + private boolean testMode = false; + private static LinkedHashMap<String, String> themeVariants = new LinkedHashMap<String, String>(); static { themeVariants.put("tests-valo", "Default"); @@ -77,11 +79,17 @@ public class ValoThemeUI extends UI { ComponentContainer viewDisplay = root.getContentContainer(); CssLayout menu = new CssLayout(); CssLayout menuItemsLayout = new CssLayout(); + { + menu.setId("testMenu"); + } private Navigator navigator; private LinkedHashMap<String, String> menuItems = new LinkedHashMap<String, String>(); @Override protected void init(VaadinRequest request) { + if (request.getParameter("test") != null) { + testMode = true; + } // Show .v-app-loading valo-menu-badge // try { // Thread.sleep(2000); @@ -159,6 +167,10 @@ public class ValoThemeUI extends UI { } + static boolean isTestMode() { + return ((ValoThemeUI) getCurrent()).testMode; + } + Component buildTestMenu() { CssLayout menu = new CssLayout(); menu.addStyleName("large-icons"); @@ -398,7 +410,7 @@ public class ValoThemeUI extends UI { // ((Hierarchical) container).setChildrenAllowed(id, false); ((Hierarchical) container).setParent(id, i); - for (int k = 1; k < 5; k++) { + for (int k = 1; k < 6; k++) { String id2 = id + " -> " + k; child = container.addItem(id2); child.getItemProperty(CAPTION_PROPERTY).setValue( diff --git a/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUITest.java b/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUITest.java new file mode 100644 index 0000000000..fdb2eabeee --- /dev/null +++ b/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUITest.java @@ -0,0 +1,239 @@ +/* + * Copyright 2000-2014 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.themes.valo; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.CssLayoutElement; +import com.vaadin.testbench.elements.LabelElement; +import com.vaadin.testbench.elements.TreeElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class ValoThemeUITest extends MultiBrowserTest { + + @Test + public void labels() throws Exception { + openTestURL("test"); + open("Labels"); + compareScreen("labels"); + } + + @Test + public void buttonsLinks() throws Exception { + openTestURL("test"); + open("Buttons & Links", "Buttons"); + compareScreen("buttonsLinks"); + } + + @Test + public void textFields() throws Exception { + openTestURL("test"); + open("Text Fields <span class=\"valo-menu-badge\">123</span>", + "Text Fields"); + compareScreen("textFields"); + } + + @Test + public void common() throws Exception { + openTestURL("test"); + open("Common UI Elements"); + compareScreen("common"); + } + + @Test + public void datefields() throws Exception { + openTestURL("test"); + open("Date Fields"); + // Note that this can look broken in IE9 because of some browser + // rendering issue... The problem seems to be in the customized + // horizontal layout in the test app + compareScreen("datefields"); + } + + @Test + public void comboboxes() throws Exception { + openTestURL("test"); + open("Combo Boxes"); + compareScreen("comboboxes"); + } + + @Test + public void selects() throws Exception { + openTestURL("test"); + open("Selects"); + compareScreen("selects"); + } + + @Test + public void checkboxes() throws Exception { + openTestURL("test"); + open("Check Boxes & Option Groups", "Check Boxes"); + compareScreen("checkboxes"); + } + + @Test + public void sliders() throws Exception { + openTestURL("test"); + open("Sliders & Progress Bars", "Sliders"); + compareScreen("sliders"); + } + + @Test + public void colorpickers() throws Exception { + openTestURL("test"); + open("Color Pickers"); + compareScreen("colorpickers"); + } + + @Test + public void menubars() throws Exception { + openTestURL("test"); + open("Menu Bars"); + compareScreen("menubars"); + } + + @Test + public void trees() throws Exception { + openTestURL("test"); + open("Trees"); + selectTreeNodeByCaption("Quid securi"); + compareScreen("trees"); + } + + private void selectTreeNodeByCaption(String string) { + WebElement e = $(TreeElement.class).first().findElement( + By.xpath("//div[@class='v-tree-node-caption']//span[text()='" + + string + "']")); + e.click(); + } + + @Test + public void tables() throws Exception { + openTestURL("test"); + open("Tables"); + compareScreen("tables"); + } + + @Test + public void dragging() throws Exception { + openTestURL("test"); + open("Drag and Drop", "Dragging Components"); + compareScreen("dragging"); + } + + @Test + public void panels() throws Exception { + openTestURL("test"); + open("Panels", "Panels & Layout panels"); + compareScreen("panels"); + } + + @Test + public void splitpanels() throws Exception { + openTestURL("test"); + open("Split Panels"); + compareScreen("splitpanels"); + } + + @Test + public void tabs() throws Exception { + openTestURL("test"); + open("Tabs <span class=\"valo-menu-badge\">123</span>", "Tabs"); + compareScreen("tabs"); + } + + @Test + public void accordions() throws Exception { + openTestURL("test"); + open("Accordions"); + compareScreen("accordions"); + } + + @Test + public void popupviews() throws Exception { + openTestURL("test"); + open("Popup Views"); + scrollTo(500, 0); + compareScreen("popupviews"); + } + + @Test + public void calendar() throws Exception { + openTestURL("test"); + scrollTo(500, 0); + open("Calendar"); + + compareScreen("calendar"); + } + + @Test + public void forms() throws Exception { + openTestURL("test"); + scrollTo(500, 0); + open("Forms"); + compareScreen("forms"); + } + + private void open(String link) { + open(link, link); + } + + private void open(String link, String caption) { + open(link, caption, 10); + } + + // FIXME: Remove this once click works properly on IE... + private void open(String link, String caption, int tries) { + if (tries <= 0) { + throw new RuntimeException( + "Tried many times but was not able to click the link..."); + } + + $(ButtonElement.class).caption(link).first().click(); + CssLayoutElement content = wrap(CssLayoutElement.class, + findElement(By.className("valo-content"))); + LabelElement captionElem = content.$(LabelElement.class).first(); + if (!captionElem.getText().equals(caption)) { + // IE ... why you fail clicks + System.err.println("Extra click needed on '" + link + + "' on remote " + getDesiredCapabilities() + " " + + getRemoteControlName()); + + open(link, caption, tries - 1); + } + } + + private void scrollTo(int top, int left) { + CssLayoutElement testMenu = $(CssLayoutElement.class).id("testMenu"); + + testBenchElement(testMenu).scroll(top); + testBenchElement(testMenu).scrollLeft(left); + } + + @Override + protected boolean requireWindowFocusForIE() { + return true; + } + + @Override + protected boolean usePersistentHoverForIE() { + return false; + } + +} |