diff options
author | Matti Hosio <mhosio@vaadin.com> | 2014-12-17 10:31:33 +0200 |
---|---|---|
committer | Matti Hosio <mhosio@vaadin.com> | 2014-12-17 10:31:33 +0200 |
commit | e547f024533bef83b8c8c8e522240f34765c894d (patch) | |
tree | 4610ad629b996df6d7882a8f9190922a467046d2 | |
parent | 8a0a1bdb4630f39214a039a2689bfa5a1431a413 (diff) | |
parent | a9f24b00e9ddcd5ca19ac2907e0bf2413f036af4 (diff) | |
download | vaadin-framework-e547f024533bef83b8c8c8e522240f34765c894d.tar.gz vaadin-framework-e547f024533bef83b8c8c8e522240f34765c894d.zip |
Merge remote-tracking branch 'origin/master' into declarative
Conflicts:
server/src/com/vaadin/ui/TextField.java
Change-Id: I289cb9ec80d494ab79aec11a43708abf5b403a00
255 files changed, 5168 insertions, 837 deletions
diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..5c304d1a4a --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. @@ -104,10 +104,15 @@ Note that the included Vaadin TestBench (browser) tests require access to a Test Building a package ===== -The distribution files can be built in two steps. +The distribution files can be built in two steps. 1. Unpack required gwt jars into the project <pre><code>ant -f gwt-files.xml unpack.gwt</code></pre> 2. Build the project by running <pre><code>ant</code></pre> in the project root directory (add -Dvaadin.version=1.2.3 to use a specific version number). + +Setting up other IDEs to Develop Vaadin 7 +========= +- Unofficial instructions + - IntelliJ IDEA: http://github.com/Saulis/vaadin-idea-workspace/ diff --git a/WebContent/VAADIN/themes/chameleon/components/notification/notification.scss b/WebContent/VAADIN/themes/chameleon/components/notification/notification.scss index 85fbb3295f..c1a8d119c7 100644 --- a/WebContent/VAADIN/themes/chameleon/components/notification/notification.scss +++ b/WebContent/VAADIN/themes/chameleon/components/notification/notification.scss @@ -9,8 +9,8 @@ div.#{$primaryStyleName} { -moz-box-shadow: 0 2px 5px rgba(0,0,0,.7); box-shadow: 0 2px 5px rgba(0,0,0,.7); //IE8 does not support rgba, using just rgb - background:rgb(255,255,255) url(../img/grad-light-top.png) repeat-x; - background:rgba(255,255,255,.90) url(../img/grad-light-top.png) repeat-x; + background:rgb(255,255,255) url(../../img/grad-light-top.png) repeat-x; + background:rgba(255,255,255,.90) url(../../img/grad-light-top.png) repeat-x; } .#{$primaryStyleName} p { diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/arrow-down.png b/WebContent/VAADIN/themes/runo/icons/icons16/arrow-down.png Binary files differnew file mode 100644 index 0000000000..ffd0ee50a5 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/arrow-down.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/arrow-left.png b/WebContent/VAADIN/themes/runo/icons/icons16/arrow-left.png Binary files differnew file mode 100644 index 0000000000..27dd25110d --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/arrow-left.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/arrow-right.png b/WebContent/VAADIN/themes/runo/icons/icons16/arrow-right.png Binary files differnew file mode 100644 index 0000000000..69bf88da8a --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/arrow-right.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/arrow-up.png b/WebContent/VAADIN/themes/runo/icons/icons16/arrow-up.png Binary files differnew file mode 100644 index 0000000000..76e5b43e08 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/arrow-up.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/attention.png b/WebContent/VAADIN/themes/runo/icons/icons16/attention.png Binary files differnew file mode 100644 index 0000000000..350de56aa5 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/attention.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/calendar.png b/WebContent/VAADIN/themes/runo/icons/icons16/calendar.png Binary files differnew file mode 100644 index 0000000000..7717a5e220 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/calendar.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/cancel.png b/WebContent/VAADIN/themes/runo/icons/icons16/cancel.png Binary files differnew file mode 100644 index 0000000000..19a0783733 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/cancel.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/document-add.png b/WebContent/VAADIN/themes/runo/icons/icons16/document-add.png Binary files differnew file mode 100644 index 0000000000..d84e349526 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/document-add.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/document-delete.png b/WebContent/VAADIN/themes/runo/icons/icons16/document-delete.png Binary files differnew file mode 100644 index 0000000000..cc3172224a --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/document-delete.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/document-doc.png b/WebContent/VAADIN/themes/runo/icons/icons16/document-doc.png Binary files differnew file mode 100644 index 0000000000..7def77428a --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/document-doc.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/document-image.png b/WebContent/VAADIN/themes/runo/icons/icons16/document-image.png Binary files differnew file mode 100644 index 0000000000..8a1bf253e8 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/document-image.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/document-pdf.png b/WebContent/VAADIN/themes/runo/icons/icons16/document-pdf.png Binary files differnew file mode 100644 index 0000000000..b58ccf7567 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/document-pdf.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/document-ppt.png b/WebContent/VAADIN/themes/runo/icons/icons16/document-ppt.png Binary files differnew file mode 100644 index 0000000000..b60f429be2 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/document-ppt.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/document-txt.png b/WebContent/VAADIN/themes/runo/icons/icons16/document-txt.png Binary files differnew file mode 100644 index 0000000000..05659b19b2 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/document-txt.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/document-web.png b/WebContent/VAADIN/themes/runo/icons/icons16/document-web.png Binary files differnew file mode 100644 index 0000000000..fcfd8685f0 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/document-web.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/document-xsl.png b/WebContent/VAADIN/themes/runo/icons/icons16/document-xsl.png Binary files differnew file mode 100644 index 0000000000..571823847f --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/document-xsl.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/document.png b/WebContent/VAADIN/themes/runo/icons/icons16/document.png Binary files differnew file mode 100644 index 0000000000..a2bab1bb0b --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/document.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/email-reply.png b/WebContent/VAADIN/themes/runo/icons/icons16/email-reply.png Binary files differnew file mode 100644 index 0000000000..be7fd2244d --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/email-reply.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/email-send.png b/WebContent/VAADIN/themes/runo/icons/icons16/email-send.png Binary files differnew file mode 100644 index 0000000000..0ef7a1c398 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/email-send.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/email.png b/WebContent/VAADIN/themes/runo/icons/icons16/email.png Binary files differnew file mode 100644 index 0000000000..68d6c93465 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/email.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/error.gif b/WebContent/VAADIN/themes/runo/icons/icons16/error.gif Binary files differnew file mode 100644 index 0000000000..c9582b2c28 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/error.gif diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/error.png b/WebContent/VAADIN/themes/runo/icons/icons16/error.png Binary files differnew file mode 100644 index 0000000000..0141e4dfc3 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/error.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/folder-add.png b/WebContent/VAADIN/themes/runo/icons/icons16/folder-add.png Binary files differnew file mode 100644 index 0000000000..48aa7c9220 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/folder-add.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/folder-delete.png b/WebContent/VAADIN/themes/runo/icons/icons16/folder-delete.png Binary files differnew file mode 100644 index 0000000000..7cc389d6b2 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/folder-delete.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/folder.png b/WebContent/VAADIN/themes/runo/icons/icons16/folder.png Binary files differnew file mode 100644 index 0000000000..f4fec377c6 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/folder.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/globe.png b/WebContent/VAADIN/themes/runo/icons/icons16/globe.png Binary files differnew file mode 100644 index 0000000000..ea4034c149 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/globe.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/help.png b/WebContent/VAADIN/themes/runo/icons/icons16/help.png Binary files differnew file mode 100644 index 0000000000..d82a8852bf --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/help.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/lock.png b/WebContent/VAADIN/themes/runo/icons/icons16/lock.png Binary files differnew file mode 100644 index 0000000000..29f1023613 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/lock.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/note.png b/WebContent/VAADIN/themes/runo/icons/icons16/note.png Binary files differnew file mode 100644 index 0000000000..efafae5570 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/note.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/ok.png b/WebContent/VAADIN/themes/runo/icons/icons16/ok.png Binary files differnew file mode 100644 index 0000000000..89591faef2 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/ok.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/reload.png b/WebContent/VAADIN/themes/runo/icons/icons16/reload.png Binary files differnew file mode 100644 index 0000000000..2c54836bff --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/reload.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/settings.png b/WebContent/VAADIN/themes/runo/icons/icons16/settings.png Binary files differnew file mode 100644 index 0000000000..019f0df663 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/settings.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/trash-full.png b/WebContent/VAADIN/themes/runo/icons/icons16/trash-full.png Binary files differnew file mode 100644 index 0000000000..7d790e6c9a --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/trash-full.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/trash.png b/WebContent/VAADIN/themes/runo/icons/icons16/trash.png Binary files differnew file mode 100644 index 0000000000..8875ae322e --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/trash.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/user.png b/WebContent/VAADIN/themes/runo/icons/icons16/user.png Binary files differnew file mode 100644 index 0000000000..522f864884 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/user.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons16/users.png b/WebContent/VAADIN/themes/runo/icons/icons16/users.png Binary files differnew file mode 100644 index 0000000000..01f2a1251c --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons16/users.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/arrow-down.png b/WebContent/VAADIN/themes/runo/icons/icons32/arrow-down.png Binary files differnew file mode 100644 index 0000000000..20c33b70fb --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/arrow-down.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/arrow-left.png b/WebContent/VAADIN/themes/runo/icons/icons32/arrow-left.png Binary files differnew file mode 100644 index 0000000000..ed2aae2cb0 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/arrow-left.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/arrow-right.png b/WebContent/VAADIN/themes/runo/icons/icons32/arrow-right.png Binary files differnew file mode 100644 index 0000000000..bd7707ec8a --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/arrow-right.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/arrow-up.png b/WebContent/VAADIN/themes/runo/icons/icons32/arrow-up.png Binary files differnew file mode 100644 index 0000000000..01c1a8ec83 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/arrow-up.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/attention.png b/WebContent/VAADIN/themes/runo/icons/icons32/attention.png Binary files differnew file mode 100644 index 0000000000..6b00733567 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/attention.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/calendar.png b/WebContent/VAADIN/themes/runo/icons/icons32/calendar.png Binary files differnew file mode 100644 index 0000000000..789ad9031c --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/calendar.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/cancel.png b/WebContent/VAADIN/themes/runo/icons/icons32/cancel.png Binary files differnew file mode 100644 index 0000000000..725240d558 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/cancel.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/document-add.png b/WebContent/VAADIN/themes/runo/icons/icons32/document-add.png Binary files differnew file mode 100644 index 0000000000..26bca0d112 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/document-add.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/document-delete.png b/WebContent/VAADIN/themes/runo/icons/icons32/document-delete.png Binary files differnew file mode 100644 index 0000000000..43e9a43e5b --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/document-delete.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/document-doc.png b/WebContent/VAADIN/themes/runo/icons/icons32/document-doc.png Binary files differnew file mode 100644 index 0000000000..8df20cfdcf --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/document-doc.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/document-edit.png b/WebContent/VAADIN/themes/runo/icons/icons32/document-edit.png Binary files differnew file mode 100644 index 0000000000..1d17383ca7 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/document-edit.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/document-image.png b/WebContent/VAADIN/themes/runo/icons/icons32/document-image.png Binary files differnew file mode 100644 index 0000000000..88c78665b8 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/document-image.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/document-pdf.png b/WebContent/VAADIN/themes/runo/icons/icons32/document-pdf.png Binary files differnew file mode 100644 index 0000000000..048a02fddf --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/document-pdf.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/document-ppt.png b/WebContent/VAADIN/themes/runo/icons/icons32/document-ppt.png Binary files differnew file mode 100644 index 0000000000..7fd7385cbd --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/document-ppt.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/document-txt.png b/WebContent/VAADIN/themes/runo/icons/icons32/document-txt.png Binary files differnew file mode 100644 index 0000000000..25264732c6 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/document-txt.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/document-web.png b/WebContent/VAADIN/themes/runo/icons/icons32/document-web.png Binary files differnew file mode 100644 index 0000000000..72fd847ac3 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/document-web.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/document-xsl.png b/WebContent/VAADIN/themes/runo/icons/icons32/document-xsl.png Binary files differnew file mode 100644 index 0000000000..2ff4607ad3 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/document-xsl.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/document.png b/WebContent/VAADIN/themes/runo/icons/icons32/document.png Binary files differnew file mode 100644 index 0000000000..1a38dcc304 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/document.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/email-reply.png b/WebContent/VAADIN/themes/runo/icons/icons32/email-reply.png Binary files differnew file mode 100644 index 0000000000..fd0203f768 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/email-reply.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/email-send.png b/WebContent/VAADIN/themes/runo/icons/icons32/email-send.png Binary files differnew file mode 100644 index 0000000000..dc34ac694d --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/email-send.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/email.png b/WebContent/VAADIN/themes/runo/icons/icons32/email.png Binary files differnew file mode 100644 index 0000000000..bef86e6cbb --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/email.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/folder-add.png b/WebContent/VAADIN/themes/runo/icons/icons32/folder-add.png Binary files differnew file mode 100644 index 0000000000..e0b78d6e1d --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/folder-add.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/folder-delete.png b/WebContent/VAADIN/themes/runo/icons/icons32/folder-delete.png Binary files differnew file mode 100644 index 0000000000..8e3c4a404c --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/folder-delete.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/folder.png b/WebContent/VAADIN/themes/runo/icons/icons32/folder.png Binary files differnew file mode 100644 index 0000000000..7577a17ac3 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/folder.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/globe.png b/WebContent/VAADIN/themes/runo/icons/icons32/globe.png Binary files differnew file mode 100644 index 0000000000..6c7d469ba2 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/globe.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/help.png b/WebContent/VAADIN/themes/runo/icons/icons32/help.png Binary files differnew file mode 100644 index 0000000000..218910c98d --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/help.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/lock.png b/WebContent/VAADIN/themes/runo/icons/icons32/lock.png Binary files differnew file mode 100644 index 0000000000..4fc16565f0 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/lock.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/note.png b/WebContent/VAADIN/themes/runo/icons/icons32/note.png Binary files differnew file mode 100644 index 0000000000..e7e035dc8c --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/note.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/ok.png b/WebContent/VAADIN/themes/runo/icons/icons32/ok.png Binary files differnew file mode 100644 index 0000000000..ac0438828c --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/ok.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/reload.png b/WebContent/VAADIN/themes/runo/icons/icons32/reload.png Binary files differnew file mode 100644 index 0000000000..c3556ec890 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/reload.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/settings.png b/WebContent/VAADIN/themes/runo/icons/icons32/settings.png Binary files differnew file mode 100644 index 0000000000..92eda74c54 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/settings.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/trash-full.png b/WebContent/VAADIN/themes/runo/icons/icons32/trash-full.png Binary files differnew file mode 100644 index 0000000000..a9707e76d6 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/trash-full.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/trash.png b/WebContent/VAADIN/themes/runo/icons/icons32/trash.png Binary files differnew file mode 100644 index 0000000000..6eaac86166 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/trash.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/user.png b/WebContent/VAADIN/themes/runo/icons/icons32/user.png Binary files differnew file mode 100644 index 0000000000..ebb5a7f9f8 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/user.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons32/users.png b/WebContent/VAADIN/themes/runo/icons/icons32/users.png Binary files differnew file mode 100644 index 0000000000..af225a9e46 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons32/users.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/arrow-down.png b/WebContent/VAADIN/themes/runo/icons/icons64/arrow-down.png Binary files differnew file mode 100644 index 0000000000..bdf5d0474e --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/arrow-down.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/arrow-left.png b/WebContent/VAADIN/themes/runo/icons/icons64/arrow-left.png Binary files differnew file mode 100644 index 0000000000..b90ed88840 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/arrow-left.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/arrow-right.png b/WebContent/VAADIN/themes/runo/icons/icons64/arrow-right.png Binary files differnew file mode 100644 index 0000000000..6331a5ddf3 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/arrow-right.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/arrow-up.png b/WebContent/VAADIN/themes/runo/icons/icons64/arrow-up.png Binary files differnew file mode 100644 index 0000000000..821fbe348f --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/arrow-up.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/attention.png b/WebContent/VAADIN/themes/runo/icons/icons64/attention.png Binary files differnew file mode 100644 index 0000000000..77265e48ee --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/attention.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/calendar.png b/WebContent/VAADIN/themes/runo/icons/icons64/calendar.png Binary files differnew file mode 100644 index 0000000000..f13fbd6efb --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/calendar.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/cancel.png b/WebContent/VAADIN/themes/runo/icons/icons64/cancel.png Binary files differnew file mode 100644 index 0000000000..1d1a719a6c --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/cancel.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/document-add.png b/WebContent/VAADIN/themes/runo/icons/icons64/document-add.png Binary files differnew file mode 100644 index 0000000000..acdcb06123 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/document-add.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/document-delete.png b/WebContent/VAADIN/themes/runo/icons/icons64/document-delete.png Binary files differnew file mode 100644 index 0000000000..2a46863b7f --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/document-delete.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/document-doc.png b/WebContent/VAADIN/themes/runo/icons/icons64/document-doc.png Binary files differnew file mode 100644 index 0000000000..455c1f15bd --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/document-doc.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/document-edit.png b/WebContent/VAADIN/themes/runo/icons/icons64/document-edit.png Binary files differnew file mode 100644 index 0000000000..6af96c9b77 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/document-edit.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/document-image.png b/WebContent/VAADIN/themes/runo/icons/icons64/document-image.png Binary files differnew file mode 100644 index 0000000000..079978e850 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/document-image.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/document-pdf.png b/WebContent/VAADIN/themes/runo/icons/icons64/document-pdf.png Binary files differnew file mode 100644 index 0000000000..cb6bc59675 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/document-pdf.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/document-ppt.png b/WebContent/VAADIN/themes/runo/icons/icons64/document-ppt.png Binary files differnew file mode 100644 index 0000000000..dd501bfbc9 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/document-ppt.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/document-txt.png b/WebContent/VAADIN/themes/runo/icons/icons64/document-txt.png Binary files differnew file mode 100644 index 0000000000..e64f746bd9 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/document-txt.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/document-web.png b/WebContent/VAADIN/themes/runo/icons/icons64/document-web.png Binary files differnew file mode 100644 index 0000000000..9d81eb5702 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/document-web.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/document-xsl.png b/WebContent/VAADIN/themes/runo/icons/icons64/document-xsl.png Binary files differnew file mode 100644 index 0000000000..6008085a34 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/document-xsl.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/document.png b/WebContent/VAADIN/themes/runo/icons/icons64/document.png Binary files differnew file mode 100644 index 0000000000..224de0bc84 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/document.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/email-reply.png b/WebContent/VAADIN/themes/runo/icons/icons64/email-reply.png Binary files differnew file mode 100644 index 0000000000..2c6f7b690d --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/email-reply.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/email-send.png b/WebContent/VAADIN/themes/runo/icons/icons64/email-send.png Binary files differnew file mode 100644 index 0000000000..9ec7198853 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/email-send.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/email.png b/WebContent/VAADIN/themes/runo/icons/icons64/email.png Binary files differnew file mode 100644 index 0000000000..e11245b2f5 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/email.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/folder-add.png b/WebContent/VAADIN/themes/runo/icons/icons64/folder-add.png Binary files differnew file mode 100644 index 0000000000..111318cc3c --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/folder-add.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/folder-delete.png b/WebContent/VAADIN/themes/runo/icons/icons64/folder-delete.png Binary files differnew file mode 100644 index 0000000000..d249983eac --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/folder-delete.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/folder.png b/WebContent/VAADIN/themes/runo/icons/icons64/folder.png Binary files differnew file mode 100644 index 0000000000..edb7b9f786 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/folder.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/globe.png b/WebContent/VAADIN/themes/runo/icons/icons64/globe.png Binary files differnew file mode 100644 index 0000000000..1786635b45 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/globe.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/help.png b/WebContent/VAADIN/themes/runo/icons/icons64/help.png Binary files differnew file mode 100644 index 0000000000..a66e8aafa6 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/help.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/lock.png b/WebContent/VAADIN/themes/runo/icons/icons64/lock.png Binary files differnew file mode 100644 index 0000000000..deaf7db0a4 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/lock.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/note.png b/WebContent/VAADIN/themes/runo/icons/icons64/note.png Binary files differnew file mode 100644 index 0000000000..1383847ed1 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/note.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/ok.png b/WebContent/VAADIN/themes/runo/icons/icons64/ok.png Binary files differnew file mode 100644 index 0000000000..dc0d00c38b --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/ok.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/reload.png b/WebContent/VAADIN/themes/runo/icons/icons64/reload.png Binary files differnew file mode 100644 index 0000000000..b91f51c67f --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/reload.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/settings.png b/WebContent/VAADIN/themes/runo/icons/icons64/settings.png Binary files differnew file mode 100644 index 0000000000..1c9b794ab0 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/settings.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/trash-full.png b/WebContent/VAADIN/themes/runo/icons/icons64/trash-full.png Binary files differnew file mode 100644 index 0000000000..81d060e509 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/trash-full.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/trash.png b/WebContent/VAADIN/themes/runo/icons/icons64/trash.png Binary files differnew file mode 100644 index 0000000000..41ef761061 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/trash.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/user.png b/WebContent/VAADIN/themes/runo/icons/icons64/user.png Binary files differnew file mode 100644 index 0000000000..60d6c6e1b3 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/user.png diff --git a/WebContent/VAADIN/themes/runo/icons/icons64/users.png b/WebContent/VAADIN/themes/runo/icons/icons64/users.png Binary files differnew file mode 100644 index 0000000000..3a42c17790 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/icons/icons64/users.png diff --git a/WebContent/VAADIN/themes/tests-valo-disabled-animations/_variables.scss b/WebContent/VAADIN/themes/tests-valo-disabled-animations/_variables.scss new file mode 100644 index 0000000000..d2411c675c --- /dev/null +++ b/WebContent/VAADIN/themes/tests-valo-disabled-animations/_variables.scss @@ -0,0 +1,3 @@ +$v-animations-enabled: false; + +@import "../valo/valo"; diff --git a/WebContent/VAADIN/themes/tests-valo-disabled-animations/styles.scss b/WebContent/VAADIN/themes/tests-valo-disabled-animations/styles.scss new file mode 100644 index 0000000000..b941c1b3d1 --- /dev/null +++ b/WebContent/VAADIN/themes/tests-valo-disabled-animations/styles.scss @@ -0,0 +1,6 @@ +@import "variables"; +@import "../tests-valo/valotest"; + +.tests-valo-disabled-animations { + @include valotest; +} diff --git a/WebContent/VAADIN/themes/valo/components/_checkbox.scss b/WebContent/VAADIN/themes/valo/components/_checkbox.scss index 3c418ec9b7..7283c4cbbf 100644 --- a/WebContent/VAADIN/themes/valo/components/_checkbox.scss +++ b/WebContent/VAADIN/themes/valo/components/_checkbox.scss @@ -99,7 +99,7 @@ } & ~ label:before { - @include valo-button-style($background-color: $background-color, $unit-size: $size, $border-radius: min(round($size/3), $v-border-radius)); + @include valo-button-style($background-color: $background-color, $unit-size: $size, $border-radius: min(round($size/3), $v-border-radius), $states: normal); padding: 0; height: round($size); } @@ -119,24 +119,6 @@ &:checked ~ label:after { color: $selection-color; } - - &[disabled] { - ~ label, - ~ label .v-icon, - ~ .v-icon { - cursor: default; - } - - ~ label:before, - ~ label:after { - @include opacity($v-disabled-opacity); - } - - &:active ~ label:after { - background: transparent; - } - } - } & > .v-icon, @@ -146,4 +128,20 @@ cursor: pointer; } + &.v-disabled { + > label, + > .v-icon { + cursor: default; + @include opacity($v-disabled-opacity); + } + + > label > .v-icon { + cursor: default; + } + + :root & > input:active ~ label:after { + background: transparent; + } + } + } diff --git a/WebContent/VAADIN/themes/valo/components/_datefield.scss b/WebContent/VAADIN/themes/valo/components/_datefield.scss index 3201288120..6d36ade43a 100644 --- a/WebContent/VAADIN/themes/valo/components/_datefield.scss +++ b/WebContent/VAADIN/themes/valo/components/_datefield.scss @@ -276,6 +276,8 @@ @include valo-overlay-style; margin-top: ceil($v-unit-size/8) !important; + margin-bottom: ceil($v-unit-size/8) !important; + margin-right: ceil($v-unit-size/8) !important; cursor: default; width: auto; diff --git a/WebContent/VAADIN/themes/valo/components/_link.scss b/WebContent/VAADIN/themes/valo/components/_link.scss index b568df1d7b..270de1aace 100644 --- a/WebContent/VAADIN/themes/valo/components/_link.scss +++ b/WebContent/VAADIN/themes/valo/components/_link.scss @@ -20,8 +20,8 @@ $v-link-cursor: pointer !default; /** * * - * @param {string} $primary-stylename (v-link) - - * @param {bool} $include-additional-styles - + * @param {string} $primary-stylename (v-link) - + * @param {bool} $include-additional-styles - * * @group link */ @@ -74,4 +74,8 @@ $v-link-cursor: pointer !default; &:hover { color: lighten($v-link-font-color, 10%); } + + &.v-disabled { + @include opacity($v-disabled-opacity); + } } diff --git a/WebContent/VAADIN/themes/valo/components/_menubar.scss b/WebContent/VAADIN/themes/valo/components/_menubar.scss index 9075eb7ba8..0f9c61d2ce 100644 --- a/WebContent/VAADIN/themes/valo/components/_menubar.scss +++ b/WebContent/VAADIN/themes/valo/components/_menubar.scss @@ -70,10 +70,6 @@ .#{$primary-stylename}-popup { @include valo-menubar-popup-style($primary-stylename); - - &.#{$primary-stylename}-popup-animate-out { - @include animation(none); - } } diff --git a/WebContent/VAADIN/themes/valo/components/_window.scss b/WebContent/VAADIN/themes/valo/components/_window.scss index ce7a530c98..23fa5338c2 100644 --- a/WebContent/VAADIN/themes/valo/components/_window.scss +++ b/WebContent/VAADIN/themes/valo/components/_window.scss @@ -89,11 +89,12 @@ $v-window-modality-curtain-background-color: #222 !default; left: 0; @include radial-gradient(circle at 50% 50%, $v-window-modality-curtain-background-color, darken($v-window-modality-curtain-background-color, valo-gradient-opacity()), $fallback: $v-window-modality-curtain-background-color); @include opacity(max(0.2, 0.8 - valo-gradient-opacity()/100%)); - @include valo-animate-in-fade($duration: 400ms, $delay: 100ms); - - .v-op12 & { - // Opera 12 has a shitbreak with the fade-in (flickers) - @include animation(none); + @if $v-animations-enabled { + @include valo-animate-in-fade($duration: 400ms, $delay: 100ms); + .v-op12 & { + // Opera 12 has a shitbreak with the fade-in (flickers) + @include animation(none); + } } } diff --git a/buildhelpers/src/com/vaadin/buildhelpers/GeneratePackageExports.java b/buildhelpers/src/com/vaadin/buildhelpers/GeneratePackageExports.java index 9dd51f8c6d..0d8f117329 100644 --- a/buildhelpers/src/com/vaadin/buildhelpers/GeneratePackageExports.java +++ b/buildhelpers/src/com/vaadin/buildhelpers/GeneratePackageExports.java @@ -26,6 +26,7 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.Manifest; import java.util.logging.Logger; +import java.util.regex.Pattern; /** * Generates Export-Packages attribute for OSGi compatible manifest. @@ -172,6 +173,9 @@ public class GeneratePackageExports { private static HashSet<String> getPackages(JarFile jar, List<String> acceptedPackagePrefixes) { HashSet<String> packages = new HashSet<String>(); + + Pattern startsWithNumber = Pattern.compile("\\.\\d"); + for (Enumeration<JarEntry> it = jar.entries(); it.hasMoreElements();) { JarEntry entry = it.nextElement(); @@ -189,6 +193,11 @@ public class GeneratePackageExports { int lastSlash = entry.getName().lastIndexOf('/'); String pkg = entry.getName().substring(0, lastSlash) .replace('/', '.'); + + if (startsWithNumber.matcher(pkg).find()) { + continue; + } + packages.add(pkg); } diff --git a/client/src/com/vaadin/client/ApplicationConfiguration.java b/client/src/com/vaadin/client/ApplicationConfiguration.java index 12b1585292..4865e38a4a 100644 --- a/client/src/com/vaadin/client/ApplicationConfiguration.java +++ b/client/src/com/vaadin/client/ApplicationConfiguration.java @@ -172,6 +172,33 @@ public class ApplicationConfiguration implements EntryPoint { return this.getConfig("versionInfo").vaadinVersion; }-*/; + /** + * Gets the version of the Atmosphere framework. + * + * @return a string with the version + * + * @see org.atmosphere.util#getRawVersion() + */ + private native String getAtmosphereVersion() + /*-{ + return this.getConfig("versionInfo").atmosphereVersion; + }-*/; + + /** + * Gets the JS version used in the Atmosphere framework. + * + * @return a string with the version + */ + private native String getAtmosphereJSVersion() + /*-{ + if ($wnd.jQueryVaadin != undefined){ + return $wnd.jQueryVaadin.atmosphere.version; + } + else { + return null; + } + }-*/; + private native String getUIDL() /*-{ return this.getConfig("uidl"); @@ -461,6 +488,24 @@ public class ApplicationConfiguration implements EntryPoint { return getJsoConfiguration(id).getVaadinVersion(); } + /** + * Return Atmosphere version. + * + * @return Atmosphere version. + */ + public String getAtmosphereVersion() { + return getJsoConfiguration(id).getAtmosphereVersion(); + } + + /** + * Return Atmosphere JS version. + * + * @return Atmosphere JS version. + */ + public String getAtmosphereJSVersion() { + return getJsoConfiguration(id).getAtmosphereJSVersion(); + } + public Class<? extends ServerConnector> getConnectorClassByEncodedTag( int tag) { Class<? extends ServerConnector> type = classes.get(tag); diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java index d7c1c54a2d..f683181857 100644 --- a/client/src/com/vaadin/client/ApplicationConnection.java +++ b/client/src/com/vaadin/client/ApplicationConnection.java @@ -66,6 +66,7 @@ import com.google.gwt.user.client.Window.ClosingHandler; import com.google.gwt.user.client.ui.HasWidgets; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.ApplicationConfiguration.ErrorMessage; +import com.vaadin.client.ApplicationConnection.ApplicationStoppedEvent; import com.vaadin.client.ResourceLoader.ResourceLoadEvent; import com.vaadin.client.ResourceLoader.ResourceLoadListener; import com.vaadin.client.communication.HasJavaScriptConnectorHelper; @@ -202,14 +203,6 @@ public class ApplicationConnection implements HasHandlers { private boolean hasActiveRequest = false; /** - * Some browsers cancel pending XHR requests when a request that might - * navigate away from the page starts (indicated by a beforeunload event). - * In that case, we should just send the request again without displaying - * any error. - */ - private boolean retryCanceledActiveRequest = false; - - /** * Webkit will ignore outgoing requests while waiting for a response to a * navigation event (indicated by a beforeunload event). When this happens, * we should keep trying to send the request every now and then until there @@ -547,14 +540,6 @@ public class ApplicationConnection implements HasHandlers { Window.addWindowClosingHandler(new ClosingHandler() { @Override public void onWindowClosing(ClosingEvent event) { - /* - * Set some flags to avoid potential problems with XHR requests, - * see javadocs of the flags for details - */ - if (hasActiveRequest()) { - retryCanceledActiveRequest = true; - } - webkitMaybeIgnoringRequests = true; } }); @@ -858,6 +843,22 @@ public class ApplicationConnection implements HasHandlers { * The contents of the request to send */ protected void doUidlRequest(final String uri, final JSONObject payload) { + doUidlRequest(uri, payload, true); + } + + /** + * Sends an asynchronous or synchronous UIDL request to the server using the + * given URI. + * + * @param uri + * The URI to use for the request. May includes GET parameters + * @param payload + * The contents of the request to send + * @param retry + * true when a status code 0 should be retried + */ + protected void doUidlRequest(final String uri, final JSONObject payload, + final boolean retry) { RequestCallback requestCallback = new RequestCallback() { @Override public void onError(Request request, Throwable exception) { @@ -887,15 +888,29 @@ public class ApplicationConnection implements HasHandlers { switch (statusCode) { case 0: - if (retryCanceledActiveRequest) { + if (retry) { /* - * Request was most likely canceled because the browser - * is maybe navigating away from the page. Just send the - * request again without displaying any error in case - * the navigation isn't carried through. + * There are 2 situations where the error can pop up: + * + * 1) Request was most likely canceled because the + * browser is maybe navigating away from the page. Just + * send the request again without displaying any error + * in case the navigation isn't carried through. + * + * 2) The browser failed to establish a network + * connection. This was observed with keep-alive + * requests, and under wi-fi roaming conditions. + * + * Status code 0 does indicate that there was no server + * side processing, so we can retry the request. */ - retryCanceledActiveRequest = false; - doUidlRequest(uri, payload); + VConsole.log("Status code 0, retrying"); + (new Timer() { + @Override + public void run() { + doUidlRequest(uri, payload, false); + } + }).schedule(100); } else { handleCommunicationError( "Invalid status code 0 (server down?)", @@ -1269,7 +1284,6 @@ public class ApplicationConnection implements HasHandlers { // so setting it after used to work but not with the #8505 changes. hasActiveRequest = false; - retryCanceledActiveRequest = false; webkitMaybeIgnoringRequests = false; if (isApplicationRunning()) { diff --git a/client/src/com/vaadin/client/VTooltip.java b/client/src/com/vaadin/client/VTooltip.java index edd1273bf5..47a1b71228 100644 --- a/client/src/com/vaadin/client/VTooltip.java +++ b/client/src/com/vaadin/client/VTooltip.java @@ -210,6 +210,14 @@ public class VTooltip extends VOverlay { x = Window.getClientWidth() - offsetWidth - MARGIN + Window.getScrollLeft(); } + + if (tooltipEventMouseX != EVENT_XY_POSITION_OUTSIDE) { + // Do not allow x to be zero, for otherwise the tooltip + // does not close when the mouse is moved (see + // isTooltipOpen()). #15129 + int minX = Window.getScrollLeft() + MARGIN; + x = Math.max(x, minX); + } return x; } @@ -245,6 +253,14 @@ public class VTooltip extends VOverlay { y = Window.getScrollTop(); } } + + if (tooltipEventMouseY != EVENT_XY_POSITION_OUTSIDE) { + // Do not allow y to be zero, for otherwise the tooltip + // does not close when the mouse is moved (see + // isTooltipOpen()). #15129 + int minY = Window.getScrollTop() + MARGIN; + y = Math.max(y, minY); + } return y; } }); @@ -323,6 +339,7 @@ public class VTooltip extends VOverlay { setPopupPosition(tooltipEventMouseX, tooltipEventMouseY); } + private int EVENT_XY_POSITION_OUTSIDE = -5000; private int tooltipEventMouseX; private int tooltipEventMouseY; @@ -332,11 +349,13 @@ public class VTooltip extends VOverlay { } private int getEventX(Event event, boolean isFocused) { - return isFocused ? -5000 : DOM.eventGetClientX(event); + return isFocused ? EVENT_XY_POSITION_OUTSIDE : DOM + .eventGetClientX(event); } private int getEventY(Event event, boolean isFocused) { - return isFocused ? -5000 : DOM.eventGetClientY(event); + return isFocused ? EVENT_XY_POSITION_OUTSIDE : DOM + .eventGetClientY(event); } @Override diff --git a/client/src/com/vaadin/client/debug/internal/InfoSection.java b/client/src/com/vaadin/client/debug/internal/InfoSection.java index a7a84f5f8f..dfb31cdd18 100644 --- a/client/src/com/vaadin/client/debug/internal/InfoSection.java +++ b/client/src/com/vaadin/client/debug/internal/InfoSection.java @@ -193,6 +193,9 @@ public class InfoSection implements Section { ApplicationConfiguration applicationConfiguration) { String clientVersion = Version.getFullVersion(); String servletVersion = applicationConfiguration.getServletVersion(); + String atmosphereVersion = applicationConfiguration + .getAtmosphereVersion(); + String jsVersion = applicationConfiguration.getAtmosphereJSVersion(); String themeVersion; boolean themeOk; @@ -213,6 +216,11 @@ public class InfoSection implements Section { addRow("Server engine version", servletVersion, servletOk ? null : ERROR_STYLE); addRow("Theme version", themeVersion, themeOk ? null : ERROR_STYLE); + if (jsVersion != null) { + addRow("Push server version", atmosphereVersion); + addRow("Push client version", jsVersion + + " (note: does not need to match server version)"); + } } /** diff --git a/client/src/com/vaadin/client/ui/VAbstractSplitPanel.java b/client/src/com/vaadin/client/ui/VAbstractSplitPanel.java index 6ee88d51dd..9d32355b70 100644 --- a/client/src/com/vaadin/client/ui/VAbstractSplitPanel.java +++ b/client/src/com/vaadin/client/ui/VAbstractSplitPanel.java @@ -199,6 +199,7 @@ public class VAbstractSplitPanel extends ComplexPanel { private void setOrientation(Orientation orientation) { this.orientation = orientation; + if (orientation == Orientation.HORIZONTAL) { splitter.getStyle().setHeight(100, Unit.PCT); splitter.getStyle().setTop(0, Unit.PX); @@ -393,107 +394,118 @@ public class VAbstractSplitPanel extends ComplexPanel { return; } - int wholeSize; - int pixelPosition; - switch (orientation) { case HORIZONTAL: - wholeSize = DOM.getElementPropertyInt(wrapper, "clientWidth"); - pixelPosition = DOM.getElementPropertyInt(splitter, "offsetLeft"); - - // reposition splitter in case it is out of box - if ((pixelPosition > 0 && pixelPosition + getSplitterSize() > wholeSize) - || (positionReversed && pixelPosition < 0)) { - pixelPosition = wholeSize - getSplitterSize(); - if (pixelPosition < 0) { - pixelPosition = 0; - } - // Move splitter within bounds, but don't remember the new value - setSplitPosition(pixelPosition + "px", false); - return; - } + horizontalOrientationUpdateSizes(); + break; + case VERTICAL: + verticalOrientationUpdateSizes(); + break; + } + } - firstContainer.getStyle().setWidth(pixelPosition, Unit.PX); - int secondContainerWidth = (wholeSize - pixelPosition - getSplitterSize()); - if (secondContainerWidth < 0) { - secondContainerWidth = 0; - } - secondContainer.getStyle().setWidth(secondContainerWidth, Unit.PX); - secondContainer.getStyle().setLeft( - pixelPosition + getSplitterSize(), Unit.PX); - - LayoutManager layoutManager = LayoutManager.get(client); - ConnectorMap connectorMap = ConnectorMap.get(client); - if (firstChild != null) { - ComponentConnector connector = connectorMap - .getConnector(firstChild); - if (connector.isRelativeWidth()) { - layoutManager.reportWidthAssignedToRelative(connector, - pixelPosition); - } else { - layoutManager.setNeedsMeasure(connector); - } + private void verticalOrientationUpdateSizes() { + int wholeSize = DOM.getElementPropertyInt(wrapper, "clientHeight"); + int pixelPosition = DOM.getElementPropertyInt(splitter, "offsetTop"); + + // reposition splitter in case it is out of box + if ((pixelPosition > 0 && pixelPosition + getSplitterSize() > wholeSize) + || (positionReversed && pixelPosition < 0)) { + pixelPosition = wholeSize - getSplitterSize(); + if (pixelPosition < 0) { + pixelPosition = 0; } - if (secondChild != null) { - ComponentConnector connector = connectorMap - .getConnector(secondChild); - if (connector.isRelativeWidth()) { - layoutManager.reportWidthAssignedToRelative(connector, - secondContainerWidth); - } else { - layoutManager.setNeedsMeasure(connector); - } + // Move splitter within bounds, but don't remember the new value + setSplitPosition(pixelPosition + "px", false); + return; + } + + firstContainer.getStyle().setHeight(pixelPosition, Unit.PX); + int secondContainerHeight = (wholeSize - pixelPosition - getSplitterSize()); + if (secondContainerHeight < 0) { + secondContainerHeight = 0; + } + secondContainer.getStyle().setHeight(secondContainerHeight, Unit.PX); + secondContainer.getStyle().setTop(pixelPosition + getSplitterSize(), + Unit.PX); + + LayoutManager layoutManager = LayoutManager.get(client); + ConnectorMap connectorMap = ConnectorMap.get(client); + if (firstChild != null) { + ComponentConnector connector = connectorMap + .getConnector(firstChild); + if (connector.isRelativeHeight()) { + layoutManager.reportHeightAssignedToRelative(connector, + pixelPosition); + } else { + layoutManager.setNeedsMeasure(connector); } - break; - case VERTICAL: - wholeSize = DOM.getElementPropertyInt(wrapper, "clientHeight"); - pixelPosition = DOM.getElementPropertyInt(splitter, "offsetTop"); - - // reposition splitter in case it is out of box - if ((pixelPosition > 0 && pixelPosition + getSplitterSize() > wholeSize) - || (positionReversed && pixelPosition < 0)) { - pixelPosition = wholeSize - getSplitterSize(); - if (pixelPosition < 0) { - pixelPosition = 0; - } - // Move splitter within bounds, but don't remember the new value - setSplitPosition(pixelPosition + "px", false); - return; + } + if (secondChild != null) { + ComponentConnector connector = connectorMap + .getConnector(secondChild); + if (connector.isRelativeHeight()) { + layoutManager.reportHeightAssignedToRelative(connector, + secondContainerHeight); + } else { + layoutManager.setNeedsMeasure(connector); } + } + } + + private void horizontalOrientationUpdateSizes() { + int wholeSize = DOM.getElementPropertyInt(wrapper, "clientWidth"); + int pixelPosition = DOM.getElementPropertyInt(splitter, "offsetLeft"); - firstContainer.getStyle().setHeight(pixelPosition, Unit.PX); - int secondContainerHeight = (wholeSize - pixelPosition - getSplitterSize()); - if (secondContainerHeight < 0) { - secondContainerHeight = 0; + // reposition splitter in case it is out of box + if ((pixelPosition > 0 && pixelPosition + getSplitterSize() > wholeSize) + || (positionReversed && pixelPosition < 0)) { + pixelPosition = wholeSize - getSplitterSize(); + if (pixelPosition < 0) { + pixelPosition = 0; } - secondContainer.getStyle() - .setHeight(secondContainerHeight, Unit.PX); - secondContainer.getStyle().setTop( - pixelPosition + getSplitterSize(), Unit.PX); - - layoutManager = LayoutManager.get(client); - connectorMap = ConnectorMap.get(client); - if (firstChild != null) { - ComponentConnector connector = connectorMap - .getConnector(firstChild); - if (connector.isRelativeHeight()) { - layoutManager.reportHeightAssignedToRelative(connector, - pixelPosition); - } else { - layoutManager.setNeedsMeasure(connector); - } + // Move splitter within bounds, but don't remember the new value + setSplitPosition(pixelPosition + "px", false); + return; + } + + firstContainer.getStyle().setWidth(pixelPosition, Unit.PX); + int secondContainerWidth = (wholeSize - pixelPosition - getSplitterSize()); + if (secondContainerWidth < 0) { + secondContainerWidth = 0; + } + secondContainer.getStyle().setWidth(secondContainerWidth, Unit.PX); + secondContainer.getStyle().setLeft(pixelPosition + getSplitterSize(), + Unit.PX); + + LayoutManager layoutManager = LayoutManager.get(client); + ConnectorMap connectorMap = ConnectorMap.get(client); + if (firstChild != null) { + ComponentConnector connector = connectorMap + .getConnector(firstChild); + if (connector.isRelativeWidth()) { + layoutManager.reportWidthAssignedToRelative(connector, + pixelPosition); + } else { + layoutManager.setNeedsMeasure(connector); } - if (secondChild != null) { - ComponentConnector connector = connectorMap - .getConnector(secondChild); - if (connector.isRelativeHeight()) { - layoutManager.reportHeightAssignedToRelative(connector, - secondContainerHeight); - } else { - layoutManager.setNeedsMeasure(connector); - } + } + if (secondChild != null) { + ComponentConnector connector = connectorMap + .getConnector(secondChild); + if (connector.isRelativeWidth()) { + layoutManager.reportWidthAssignedToRelative(connector, + secondContainerWidth); + } else { + layoutManager.setNeedsMeasure(connector); } - break; + } + + // previous layout pass may have changed the position already, needs to + // be reset before calculating which positioning should be used + secondContainer.getStyle().setPosition(Position.ABSOLUTE); + if (getOffsetHeight() == 0) { + secondContainer.getStyle().setPosition(Position.RELATIVE); } } diff --git a/client/src/com/vaadin/client/ui/VAccordion.java b/client/src/com/vaadin/client/ui/VAccordion.java index 3e89958a98..ff77a8cb91 100644 --- a/client/src/com/vaadin/client/ui/VAccordion.java +++ b/client/src/com/vaadin/client/ui/VAccordion.java @@ -159,6 +159,8 @@ public class VAccordion extends VTabsheetBase { */ public class StackItem extends ComplexPanel implements ClickHandler { + private Widget widget; + public void setHeight(int height) { if (height == -1) { super.setHeight(""); @@ -171,10 +173,7 @@ public class VAccordion extends VTabsheetBase { } public Widget getComponent() { - if (getWidgetCount() < 2) { - return null; - } - return getWidget(1); + return widget; } @Override @@ -268,24 +267,26 @@ public class VAccordion extends VTabsheetBase { } public Widget getChildWidget() { - if (getWidgetCount() > 1) { - return getWidget(1); - } else { - return null; - } + return widget; } public void replaceWidget(Widget newWidget) { - if (getWidgetCount() > 1) { - Widget oldWidget = getWidget(1); - remove(oldWidget); - widgets.remove(oldWidget); + if (widget != null) { + widgets.remove(widget); + if (open) { + remove(widget); + } } - add(newWidget, content); + widget = newWidget; widgets.add(newWidget); + if (open) { + add(widget, content); + } + } public void open() { + add(widget, content); open = true; content.getStyle().setTop(getCaptionHeight(), Unit.PX); content.getStyle().setLeft(0, Unit.PX); @@ -298,6 +299,9 @@ public class VAccordion extends VTabsheetBase { } public void close() { + if (widget != null) { + remove(widget); + } content.getStyle().setVisibility(Visibility.HIDDEN); content.getStyle().setTop(-100000, Unit.PX); content.getStyle().setLeft(-100000, Unit.PX); @@ -322,10 +326,10 @@ public class VAccordion extends VTabsheetBase { * new content */ public void setContent(Widget newWidget) { - if (getChildWidget() == null) { - add(newWidget, content); + if (widget == null) { + widget = newWidget; widgets.add(newWidget); - } else if (getChildWidget() != newWidget) { + } else if (widget != newWidget) { replaceWidget(newWidget); } if (isOpen() && isDynamicHeight()) { diff --git a/client/src/com/vaadin/client/ui/VCustomLayout.java b/client/src/com/vaadin/client/ui/VCustomLayout.java index 3b2b007b5b..f5d572007a 100644 --- a/client/src/com/vaadin/client/ui/VCustomLayout.java +++ b/client/src/com/vaadin/client/ui/VCustomLayout.java @@ -158,7 +158,7 @@ public class VCustomLayout extends ComplexPanel { // TODO prefix img src:s here with a regeps, cannot work further with IE - String relImgPrefix = themeUri + "/layouts/"; + String relImgPrefix = Util.escapeAttribute(themeUri + "/layouts/"); // prefix all relative image elements to point to theme dir with a // regexp search diff --git a/client/src/com/vaadin/client/ui/VMenuBar.java b/client/src/com/vaadin/client/ui/VMenuBar.java index 5102e6faea..66160e691d 100644 --- a/client/src/com/vaadin/client/ui/VMenuBar.java +++ b/client/src/com/vaadin/client/ui/VMenuBar.java @@ -476,7 +476,8 @@ public class VMenuBar extends SimpleFocusablePanel implements if (menuVisible && visibleChildMenu != item.getSubMenu() && popup != null) { - popup.hide(); + // #15255 - disable animation-in/out when hide in this case + popup.hide(false, false, false); } if (menuVisible && item.getSubMenu() != null @@ -707,9 +708,22 @@ public class VMenuBar extends SimpleFocusablePanel implements * Recursively hide all child menus */ public void hideChildren() { + hideChildren(true, true); + } + + /** + * + * Recursively hide all child menus + * + * @param animateIn + * enable/disable animate-in animation when hide popup + * @param animateOut + * enable/disable animate-out animation when hide popup + */ + public void hideChildren(boolean animateIn, boolean animateOut) { if (visibleChildMenu != null) { - visibleChildMenu.hideChildren(); - popup.hide(); + visibleChildMenu.hideChildren(animateIn, animateOut); + popup.hide(false, animateIn, animateOut); } } @@ -1326,7 +1340,8 @@ public class VMenuBar extends SimpleFocusablePanel implements VMenuBar root = getParentMenu(); root.getSelected().getSubMenu().setSelected(null); - root.hideChildren(); + // #15255 - disable animate-in/out when hide popup + root.hideChildren(false, false); // Get the root menus items and select the previous one int idx = root.getItems().indexOf(root.getSelected()); @@ -1383,8 +1398,9 @@ public class VMenuBar extends SimpleFocusablePanel implements root = root.getParentMenu(); } - // Hide the submenu - root.hideChildren(); + // Hide the submenu (#15255 - disable animate-in/out when hide + // popup) + root.hideChildren(false, false); // Get the root menus items and select the next one int idx = root.getItems().indexOf(root.getSelected()); diff --git a/client/src/com/vaadin/client/ui/VOverlay.java b/client/src/com/vaadin/client/ui/VOverlay.java index dfd81faf94..9071b6ee47 100644 --- a/client/src/com/vaadin/client/ui/VOverlay.java +++ b/client/src/com/vaadin/client/ui/VOverlay.java @@ -51,7 +51,7 @@ import com.vaadin.client.Util; * temporary float over other components like context menus etc. This is to deal * stacking order correctly with VWindow objects. * </p> - * + * * <h3>Shadow</h3> * <p> * The separate shadow element underneath the main overlay element is <strong> @@ -62,7 +62,7 @@ import com.vaadin.client.Util; * supports, add <code>-webkit-box-shadow</code> and the standard * <code>box-shadow</code> properties. * </p> - * + * * <p> * For IE8, which doesn't support CSS box-shadow, you can use the proprietary * DropShadow filter. It doesn't provide the exact same features as box-shadow, @@ -70,7 +70,7 @@ import com.vaadin.client.Util; * border or a pseudo-element underneath the overlay which mimics a shadow, or * any combination of these. * </p> - * + * * <p> * Read more about the DropShadow filter from <a * href="http://msdn.microsoft.com/en-us/library/ms532985(v=vs.85).aspx" @@ -164,7 +164,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { * Shadow element style. If an extending class wishes to use a different * style of shadow, it can use setShadowStyle(String) to give the shadow * element a new style name. - * + * * @deprecated See main JavaDoc for VOverlay */ @Deprecated @@ -187,9 +187,9 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { /** * The shadow element for this overlay. - * + * * @deprecated See main JavaDoc for VOverlay - * + * */ @Deprecated private Element shadow; @@ -218,7 +218,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { /** * The HTML snippet that is used to render the actual shadow. In consists of * nine different DIV-elements with the following class names: - * + * * <pre> * .v-shadow[-stylename] * ---------------------------------------------- @@ -231,9 +231,9 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { * | .bottom-left | .bottom | .bottom-right | * ---------------------------------------------- * </pre> - * + * * See default theme 'shadow.css' for implementation example. - * + * * @deprecated See main JavaDoc for VOverlay */ @Deprecated @@ -280,7 +280,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { * Return true if a separate shadow div should be used. Since Vaadin 7.3, * shadows are implemented with CSS box-shadow. Thus, a shadow div is only * used for IE8 by default. - * + * * @deprecated See main JavaDoc for VOverlay * @since 7.3 * @return true to use a shadow div @@ -294,10 +294,10 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { * Method to control whether DOM elements for shadow are added. With this * method subclasses can control displaying of shadow also after the * constructor. - * + * * @param enabled * true if shadow should be displayed - * + * * @deprecated See main JavaDoc for VOverlay */ @Deprecated @@ -361,7 +361,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { /** * Set the z-index (visual stack position) for this overlay. - * + * * @param zIndex * The new z-index */ @@ -574,12 +574,12 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { * Sets the shadow style for this overlay. Will override any previous style * for the shadow. The default style name is defined by CLASSNAME_SHADOW. * The given style will be prefixed with CLASSNAME_SHADOW. - * + * * @param style * The new style name for the shadow element. Will be prefixed by * CLASSNAME_SHADOW, e.g. style=='foobar' -> actual style * name=='v-shadow-foobar'. - * + * * @deprecated See main JavaDoc for VOverlay */ @Deprecated @@ -593,7 +593,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { * Extending classes should always call this method after they change the * size of overlay without using normal 'setWidth(String)' and * 'setHeight(String)' methods (if not calling super.setWidth/Height). - * + * */ public void positionOrSizeUpdated() { positionOrSizeUpdated(1.0); @@ -612,7 +612,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { * elements. Can be used to animate the related elements, using the * 'progress' parameter (used to animate the shadow in sync with GWT * PopupPanel's default animation 'PopupPanel.AnimationType.CENTER'). - * + * * @param progress * A value between 0.0 and 1.0, indicating the progress of the * animation (0=start, 1=end). @@ -721,7 +721,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { * Returns true if we should add a shim iframe below the overlay to deal * with zindex issues with PDFs and applets. Can be overriden to disable * shim iframes if they are not needed. - * + * * @return true if a shim iframe should be added, false otherwise */ protected boolean needsShimElement() { @@ -783,13 +783,13 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { /** * Enables or disables sinking the events of the shadow to the same * onBrowserEvent as events to the actual overlay goes. - * + * * Please note, that if you enable this, you can't assume that e.g. * event.getEventTarget returns an element inside the DOM structure of the * overlay - * + * * @param sinkShadowEvents - * + * * @deprecated See main JavaDoc for VOverlay */ @Deprecated @@ -813,7 +813,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { /** * Get owner (Widget that made this VOverlay, not the layout parent) of * VOverlay - * + * * @return Owner (creator) or null if not defined */ public Widget getOwner() { @@ -823,7 +823,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { /** * Set owner (Widget that made this VOverlay, not the layout parent) of * VOverlay - * + * * @param owner * Owner (creator) of VOverlay */ @@ -834,7 +834,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { /** * Get the {@link ApplicationConnection} that this overlay belongs to. If * it's not set, {@link #getOwner()} is used to figure it out. - * + * * @return */ protected ApplicationConnection getApplicationConnection() { @@ -854,7 +854,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { /** * Gets the 'overlay container' element. Tries to find the current * {@link ApplicationConnection} using {@link #getApplicationConnection()}. - * + * * @return the overlay container element for the current * {@link ApplicationConnection} or another element if the current * {@link ApplicationConnection} cannot be determined. @@ -878,7 +878,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { * {@link ApplicationConnection}. Each overlay should be created in a * overlay container element, so that the correct theme and styles can be * applied. - * + * * @param ac * A reference to {@link ApplicationConnection} * @return The overlay container @@ -905,7 +905,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { /** * Set the label of the container element, where tooltip, notification and * dialgs are added to. - * + * * @param applicationConnection * the application connection for which to change the label * @param overlayContainerLabel @@ -938,10 +938,10 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { /** * Gets the visual viewport width, which is useful for e.g iOS where the * view can be zoomed in while keeping the layout viewport intact. - * + * * Falls back to layout viewport; for those browsers/devices the difference * is that the scrollbar with is included (if there is a scrollbar). - * + * * @since 7.0.7 * @return */ @@ -957,10 +957,10 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { /** * Gets the visual viewport height, which is useful for e.g iOS where the * view can be zoomed in while keeping the layout viewport intact. - * + * * Falls back to layout viewport; for those browsers/devices the difference * is that the scrollbar with is included (if there is a scrollbar). - * + * * @since 7.0.7 * @return */ @@ -1000,10 +1000,33 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { */ @Override public void hide(final boolean autoClosed) { + hide(autoClosed, true, true); + } + + /** + * + * Hides the popup and detaches it from the page. This has no effect if it + * is not currently showing. Animation-in, animation-out can be + * enable/disabled for different use cases. + * + * @see com.google.gwt.user.client.ui.PopupPanel#hide(boolean) + * + * @param autoClosed + * the value that will be passed to + * {@link CloseHandler#onClose(CloseEvent)} when the popup is + * closed + * @param animateIn + * enable/disable animate-in animation + * @param animateOut + * enable/disable animate-out animation + */ + public void hide(final boolean autoClosed, final boolean animateIn, + final boolean animateOut) { if (BrowserInfo.get().isIE8() || BrowserInfo.get().isIE9()) { super.hide(autoClosed); } else { - if (getStyleName().contains(ADDITIONAL_CLASSNAME_ANIMATE_IN)) { + if (animateIn + && getStyleName().contains(ADDITIONAL_CLASSNAME_ANIMATE_IN)) { AnimationUtil.addAnimationEndListener(getElement(), new AnimationEndListener() { @Override @@ -1029,7 +1052,9 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { animationName = ""; } - if (animationName.contains(ADDITIONAL_CLASSNAME_ANIMATE_OUT)) { + if (animateOut + && animationName + .contains(ADDITIONAL_CLASSNAME_ANIMATE_OUT)) { // Disable GWT PopupPanel closing animation if used setAnimationEnabled(false); diff --git a/client/src/com/vaadin/client/ui/VPopupCalendar.java b/client/src/com/vaadin/client/ui/VPopupCalendar.java index 51b2ee22ec..cf88ceb8d6 100644 --- a/client/src/com/vaadin/client/ui/VPopupCalendar.java +++ b/client/src/com/vaadin/client/ui/VPopupCalendar.java @@ -27,6 +27,10 @@ import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.DomEvent; import com.google.gwt.event.dom.client.KeyCodes; +import com.google.gwt.event.dom.client.MouseOutEvent; +import com.google.gwt.event.dom.client.MouseOutHandler; +import com.google.gwt.event.dom.client.MouseOverEvent; +import com.google.gwt.event.dom.client.MouseOverHandler; import com.google.gwt.event.logical.shared.CloseEvent; import com.google.gwt.event.logical.shared.CloseHandler; import com.google.gwt.i18n.client.DateTimeFormat; @@ -42,6 +46,7 @@ import com.google.gwt.user.client.ui.PopupPanel.PositionCallback; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.BrowserInfo; +import com.vaadin.client.ComputedStyle; import com.vaadin.client.VConsole; import com.vaadin.client.ui.VCalendarPanel.FocusOutListener; import com.vaadin.client.ui.VCalendarPanel.SubmitListener; @@ -76,6 +81,15 @@ public class VPopupCalendar extends VTextualDate implements Field, private boolean open = false; + /* + * #14857: If calendarToggle button is clicked when calendar popup is + * already open we should prevent calling openCalendarPanel() in onClick, + * since we don't want to reopen it again right after it closes. + */ + private boolean preventOpenPopupCalendar = false; + private boolean cursorOverCalendarToggleButton = false; + private boolean toggleButtonClosesWithGuarantee = false; + private boolean textFieldEnabled = true; private String captionId; @@ -89,6 +103,21 @@ public class VPopupCalendar extends VTextualDate implements Field, calendarToggle.setText(""); calendarToggle.addClickHandler(this); + + calendarToggle.addDomHandler(new MouseOverHandler() { + @Override + public void onMouseOver(MouseOverEvent event) { + cursorOverCalendarToggleButton = true; + } + }, MouseOverEvent.getType()); + + calendarToggle.addDomHandler(new MouseOutHandler() { + @Override + public void onMouseOut(MouseOutEvent event) { + cursorOverCalendarToggleButton = false; + } + }, MouseOutEvent.getType()); + // -2 instead of -1 to avoid FocusWidget.onAttach to reset it calendarToggle.getElement().setTabIndex(-2); @@ -372,60 +401,7 @@ public class VPopupCalendar extends VTextualDate implements Field, // clear previous values popup.setWidth(""); popup.setHeight(""); - popup.setPopupPositionAndShow(new PositionCallback() { - @Override - public void setPosition(int offsetWidth, int offsetHeight) { - final int w = offsetWidth; - final int h = offsetHeight; - final int browserWindowWidth = Window.getClientWidth() - + Window.getScrollLeft(); - final int browserWindowHeight = Window.getClientHeight() - + Window.getScrollTop(); - int t = calendarToggle.getAbsoluteTop(); - int l = calendarToggle.getAbsoluteLeft(); - - // Add a little extra space to the right to avoid - // problems with IE7 scrollbars and to make it look - // nicer. - int extraSpace = 30; - - boolean overflowRight = false; - if (l + +w + extraSpace > browserWindowWidth) { - overflowRight = true; - // Part of the popup is outside the browser window - // (to the right) - l = browserWindowWidth - w - extraSpace; - } - - if (t + h + calendarToggle.getOffsetHeight() + 30 > browserWindowHeight) { - // Part of the popup is outside the browser window - // (below) - t = browserWindowHeight - h - - calendarToggle.getOffsetHeight() - 30; - if (!overflowRight) { - // Show to the right of the popup button unless we - // are in the lower right corner of the screen - l += calendarToggle.getOffsetWidth(); - } - } - - popup.setPopupPosition(l, - t + calendarToggle.getOffsetHeight() + 2); - - /* - * We have to wait a while before focusing since the popup - * needs to be opened before we can focus - */ - Timer focusTimer = new Timer() { - @Override - public void run() { - setFocus(true); - } - }; - - focusTimer.schedule(100); - } - }); + popup.setPopupPositionAndShow(new PopupPositionCallback()); } else { VConsole.error("Cannot reopen popup, it is already open!"); } @@ -441,7 +417,10 @@ public class VPopupCalendar extends VTextualDate implements Field, @Override public void onClick(ClickEvent event) { if (event.getSource() == calendarToggle && isEnabled()) { - openCalendarPanel(); + if (!preventOpenPopupCalendar) { + openCalendarPanel(); + } + preventOpenPopupCalendar = false; } } @@ -464,15 +443,14 @@ public class VPopupCalendar extends VTextualDate implements Field, focus(); } - // TODO resolve what the "Sigh." is all about and document it here - // Sigh. - Timer t = new Timer() { - @Override - public void run() { - open = false; - } - }; - t.schedule(100); + open = false; + + if (cursorOverCalendarToggleButton + && !toggleButtonClosesWithGuarantee) { + preventOpenPopupCalendar = true; + } + + toggleButtonClosesWithGuarantee = false; } } @@ -572,6 +550,7 @@ public class VPopupCalendar extends VTextualDate implements Field, */ public void closeCalendarPanel() { if (open) { + toggleButtonClosesWithGuarantee = true; popup.hide(true); } } @@ -642,4 +621,113 @@ public class VPopupCalendar extends VTextualDate implements Field, calendar.setRangeEnd(rangeEnd); } + private class PopupPositionCallback implements PositionCallback { + + @Override + public void setPosition(int offsetWidth, int offsetHeight) { + final int width = offsetWidth; + final int height = offsetHeight; + final int browserWindowWidth = Window.getClientWidth() + + Window.getScrollLeft(); + final int windowHeight = Window.getClientHeight() + + Window.getScrollTop(); + int left = calendarToggle.getAbsoluteLeft(); + + // Add a little extra space to the right to avoid + // problems with IE7 scrollbars and to make it look + // nicer. + int extraSpace = 30; + + boolean overflow = left + width + extraSpace > browserWindowWidth; + if (overflow) { + // Part of the popup is outside the browser window + // (to the right) + left = browserWindowWidth - width - extraSpace; + } + + int top = calendarToggle.getAbsoluteTop(); + int extraHeight = 2; + boolean verticallyRepositioned = false; + ComputedStyle style = new ComputedStyle(popup.getElement()); + int[] margins = style.getMargin(); + int desiredPopupBottom = top + height + + calendarToggle.getOffsetHeight() + margins[0] + + margins[2]; + + if (desiredPopupBottom > windowHeight) { + int updatedLeft = left; + left = getLeftPosition(left, width, style, overflow); + + // if position has not been changed then it means there is no + // space to make popup fully visible + if (updatedLeft == left) { + // let's try to show popup on the top of the field + int updatedTop = top - extraHeight - height - margins[0] + - margins[2]; + verticallyRepositioned = updatedTop >= 0; + if (verticallyRepositioned) { + top = updatedTop; + } + } + // Part of the popup is outside the browser window + // (below) + if (!verticallyRepositioned) { + verticallyRepositioned = true; + top = windowHeight - height - extraSpace + extraHeight; + } + } + if (verticallyRepositioned) { + popup.setPopupPosition(left, top); + } else { + popup.setPopupPosition(left, + top + calendarToggle.getOffsetHeight() + extraHeight); + } + doSetFocus(); + } + + private int getLeftPosition(int left, int width, ComputedStyle style, + boolean overflow) { + if (positionRightSide()) { + // Show to the right of the popup button unless we + // are in the lower right corner of the screen + if (overflow) { + return left; + } else { + return left + calendarToggle.getOffsetWidth(); + } + } else { + int[] margins = style.getMargin(); + int desiredLeftPosition = calendarToggle.getAbsoluteLeft() + - width - margins[1] - margins[3]; + if (desiredLeftPosition >= 0) { + return desiredLeftPosition; + } else { + return left; + } + } + } + + private boolean positionRightSide() { + int buttonRightSide = calendarToggle.getAbsoluteLeft() + + calendarToggle.getOffsetWidth(); + int textRightSide = text.getAbsoluteLeft() + text.getOffsetWidth(); + return buttonRightSide >= textRightSide; + } + + private void doSetFocus() { + /* + * We have to wait a while before focusing since the popup needs to + * be opened before we can focus + */ + Timer focusTimer = new Timer() { + @Override + public void run() { + setFocus(true); + } + }; + + focusTimer.schedule(100); + } + } + } diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java index 6c241f1033..14e4c658ad 100644 --- a/client/src/com/vaadin/client/ui/VScrollTable.java +++ b/client/src/com/vaadin/client/ui/VScrollTable.java @@ -5392,6 +5392,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, private Map<TableCellElement, TooltipInfo> cellToolTips = new HashMap<TableCellElement, TooltipInfo>(); private boolean isDragging = false; private String rowStyle = null; + protected boolean applyZeroWidthFix = true; private VScrollTableRow(int rowKey) { this.rowKey = rowKey; @@ -5497,7 +5498,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, * definition of zero width table cells. Instead, use 1px * and compensate with a negative margin. */ - if (width == 0) { + if (applyZeroWidthFix && width == 0) { wrapperWidth = 1; wrapperStyle.setMarginRight(-1, Unit.PX); } else { diff --git a/client/src/com/vaadin/client/ui/VTabsheet.java b/client/src/com/vaadin/client/ui/VTabsheet.java index bcca117395..090f83c066 100644 --- a/client/src/com/vaadin/client/ui/VTabsheet.java +++ b/client/src/com/vaadin/client/ui/VTabsheet.java @@ -78,6 +78,8 @@ import com.vaadin.shared.ui.tabsheet.TabsheetState; public class VTabsheet extends VTabsheetBase implements Focusable, SubPartAware { + private static final String PREV_SCROLLER_DISABLED_CLASSNAME = "Prev-disabled"; + private static class VCloseEvent { private Tab tab; @@ -1069,6 +1071,22 @@ public class VTabsheet extends VTabsheetBase implements Focusable, SubPartAware updateOpenTabSize(); } + private boolean isAllTabsBeforeIndexInvisible() { + boolean invisible = true; + for (int i = 0; i < scrollerIndex; i++) { + invisible = invisible & !tb.getTab(i).isVisible(); + } + return invisible; + } + + private boolean isScrollerPrevDisabled() { + return scrollerPrev.getClassName().contains(PREV_SCROLLER_DISABLED_CLASSNAME); + } + + private boolean isIndexSkippingHiddenTabs() { + return isAllTabsBeforeIndexInvisible() && isScrollerPrevDisabled(); + } + @Override public void renderTab(final TabState tabState, int index) { Tab tab = tb.getTab(index); @@ -1080,10 +1098,15 @@ public class VTabsheet extends VTabsheetBase implements Focusable, SubPartAware tab.setEnabledOnServer((!disabledTabKeys.contains(tabKeys.get(index)))); tab.setHiddenOnServer(!tabState.visible); - if (scrolledOutOfView(index)) { + if (scrolledOutOfView(index) && !isIndexSkippingHiddenTabs()) { // Should not set tabs visible if they are scrolled out of view tab.setVisible(false); } else { + //reset the scroller index back to zero if tab is visible + //again and tab is in view + if(isIndexSkippingHiddenTabs() && tabState.visible) { + scrollerIndex = 0; + } tab.setVisible(tabState.visible); } @@ -1223,7 +1246,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, SubPartAware if (tb.getTabCount() > 0 && tb.isVisible() && (scrolled || clipped)) { scroller.getStyle().clearDisplay(); DOM.setElementProperty(scrollerPrev, "className", - SCROLLER_CLASSNAME + (scrolled ? "Prev" : "Prev-disabled")); + SCROLLER_CLASSNAME + (scrolled ? "Prev" : PREV_SCROLLER_DISABLED_CLASSNAME)); DOM.setElementProperty(scrollerNext, "className", SCROLLER_CLASSNAME + (clipped ? "Next" : "Next-disabled")); diff --git a/client/src/com/vaadin/client/ui/VTreeTable.java b/client/src/com/vaadin/client/ui/VTreeTable.java index 9b7e9702b2..9e5940a2f2 100644 --- a/client/src/com/vaadin/client/ui/VTreeTable.java +++ b/client/src/com/vaadin/client/ui/VTreeTable.java @@ -155,6 +155,8 @@ public class VTreeTable extends VScrollTable { public VTreeTableRow(UIDL uidl, char[] aligns2) { super(uidl, aligns2); + // this fix causes #15118 and doesn't work for treetable anyway + applyZeroWidthFix = false; } @Override diff --git a/client/src/com/vaadin/client/ui/accordion/AccordionConnector.java b/client/src/com/vaadin/client/ui/accordion/AccordionConnector.java index c0caded759..72aa2dbdfd 100644 --- a/client/src/com/vaadin/client/ui/accordion/AccordionConnector.java +++ b/client/src/com/vaadin/client/ui/accordion/AccordionConnector.java @@ -50,12 +50,13 @@ public class AccordionConnector extends TabsheetBaseConnector implements StackItem selectedItem = getWidget().getStackItem( getWidget().selectedItemIndex); - getWidget().open(getWidget().selectedItemIndex); - ComponentConnector contentConnector = getChildComponents().get(0); if (contentConnector != null) { selectedItem.setContent(contentConnector.getWidget()); } + + getWidget().open(getWidget().selectedItemIndex); + } else if (getWidget().getOpenStackItem() != null) { getWidget().close(getWidget().getOpenStackItem()); } diff --git a/client/src/com/vaadin/client/ui/customlayout/CustomLayoutConnector.java b/client/src/com/vaadin/client/ui/customlayout/CustomLayoutConnector.java index a37ce9af38..80979587b9 100644 --- a/client/src/com/vaadin/client/ui/customlayout/CustomLayoutConnector.java +++ b/client/src/com/vaadin/client/ui/customlayout/CustomLayoutConnector.java @@ -34,6 +34,8 @@ import com.vaadin.ui.CustomLayout; public class CustomLayoutConnector extends AbstractLayoutConnector implements SimpleManagedLayout, Paintable { + private boolean templateUpdated; + @Override public CustomLayoutState getState() { return (CustomLayoutState) super.getState(); @@ -62,7 +64,7 @@ public class CustomLayoutConnector extends AbstractLayoutConnector implements } private void updateHtmlTemplate() { - if (getWidget().hasTemplate()) { + if (templateUpdated) { // We (currently) only do this once. You can't change the template // later on. return; @@ -76,14 +78,23 @@ public class CustomLayoutConnector extends AbstractLayoutConnector implements templateContents = getConnection().getResource( "layouts/" + templateName + ".html"); if (templateContents == null) { - templateContents = "<em>Layout file layouts/" - + templateName - + ".html is missing. Components will be drawn for debug purposes.</em>"; + // Template missing -> show debug notice and render components + // in order. + getWidget() + .getElement() + .setInnerHTML( + "<em>Layout file layouts/" + + templateName + + ".html is missing. Components will be drawn for debug purposes.</em>"); } } - getWidget().initializeHTML(templateContents, - getConnection().getThemeUri()); + if (templateContents != null) { + // Template ok -> initialize. + getWidget().initializeHTML(templateContents, + getConnection().getThemeUri()); + } + templateUpdated = true; } @Override diff --git a/client/src/com/vaadin/client/ui/dd/VDragEvent.java b/client/src/com/vaadin/client/ui/dd/VDragEvent.java index 6291a38e42..45f89bdb87 100644 --- a/client/src/com/vaadin/client/ui/dd/VDragEvent.java +++ b/client/src/com/vaadin/client/ui/dd/VDragEvent.java @@ -244,6 +244,11 @@ public class VDragEvent { public void createDragImage(com.google.gwt.user.client.Element element, boolean alignImageToEvent) { Element cloneNode = (Element) element.cloneNode(true); + + // Set size explicitly for cloned node to avoid stretching #14617. + cloneNode.getStyle().setWidth(element.getOffsetWidth(), Unit.PX); + cloneNode.getStyle().setHeight(element.getOffsetHeight(), Unit.PX); + syncContent(element, cloneNode); if (BrowserInfo.get().isIE()) { if (cloneNode.getTagName().toLowerCase().equals("tr")) { diff --git a/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java b/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java index aace349392..0c09ae49c6 100644 --- a/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java +++ b/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java @@ -152,20 +152,7 @@ public abstract class AbstractOrderedLayoutConnector extends public void onElementResize(ElementResizeEvent e) { updateLayoutHeight(); if (needsExpand()) { - /* - * updateLayoutHeight causes calling of - * getLayoutManager().setNeedsMeasure(this) which informs this - * LayoutManager that the size of a component might have - * changed. Then a new layout phase is scheduled. So - * updateExpandCompensation must be delayed until layout phase - * will be completed. #12672 - */ - Scheduler.get().scheduleFinally(new ScheduledCommand() { - @Override - public void execute() { - getWidget().updateExpandCompensation(); - } - }); + getWidget().updateExpandCompensation(); } } }; diff --git a/client/src/com/vaadin/client/ui/textfield/TextFieldConnector.java b/client/src/com/vaadin/client/ui/textfield/TextFieldConnector.java index 42b045005f..cba827bcef 100644 --- a/client/src/com/vaadin/client/ui/textfield/TextFieldConnector.java +++ b/client/src/com/vaadin/client/ui/textfield/TextFieldConnector.java @@ -84,13 +84,20 @@ public class TextFieldConnector extends AbstractFieldConnector implements /* * We skip the text content update if field has been repainted, but text * has not been changed. Additional sanity check verifies there is no - * change in the que (in which case we count more on the server side + * change in the queue (in which case we count more on the server side * value). */ - if (!(uidl - .getBooleanAttribute(TextFieldConstants.ATTR_NO_VALUE_CHANGE_BETWEEN_PAINTS) - && getWidget().valueBeforeEdit != null && text - .equals(getWidget().valueBeforeEdit))) { + + boolean valueChanged = !uidl + .getBooleanAttribute(TextFieldConstants.ATTR_NO_VALUE_CHANGE_BETWEEN_PAINTS); + // null check is not enough since the value is sometimes null but + // sometimes empty. Fix for #15144 + boolean valueBeforeEditEmpty = getWidget().valueBeforeEdit == null + || getWidget().valueBeforeEdit.isEmpty(); + boolean textDoesNotEqualOldValue = !text + .equals(getWidget().valueBeforeEdit); + + if (valueChanged || valueBeforeEditEmpty || textDoesNotEqualOldValue) { getWidget().updateFieldContent(text); } diff --git a/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java b/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java index 6cd0630137..cb70fc7a39 100644 --- a/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java +++ b/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java @@ -10,6 +10,7 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { private static final String FIREFOX30_WINDOWS = "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.0.6) Gecko/2009011913 Firefox/3.0.6"; private static final String FIREFOX30_LINUX = "Mozilla/5.0 (X11; U; Linux x86_64; es-ES; rv:1.9.0.12) Gecko/2009070811 Ubuntu/9.04 (jaunty) Firefox/3.0.12"; + private static final String FIREFOX33_ANDROID = "Mozilla/5.0 (Android; Tablet; rv:33.0) Gecko/33.0 Firefox/33.0"; private static final String FIREFOX35_WINDOWS = "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.8) Gecko/20100202 Firefox/3.5.8 (.NET CLR 3.5.30729) FirePHP/0.4"; private static final String FIREFOX36_WINDOWS = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6 (.NET CLR 3.5.30729)"; private static final String FIREFOX36B_MAC = "UAString mozilla/5.0 (macintosh; u; intel mac os x 10.6; en-us; rv:1.9.2) gecko/20100115 firefox/3.6"; @@ -209,6 +210,15 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { assertLinux(bd); } + public void testFirefox33Android() { + VBrowserDetails bd = new VBrowserDetails(FIREFOX33_ANDROID); + assertGecko(bd); + assertFirefox(bd); + assertBrowserMajorVersion(bd, 33); + assertBrowserMinorVersion(bd, 0); + assertAndroid(bd, -1, -1); + } + public void testFirefox35() { VBrowserDetails bd = new VBrowserDetails(FIREFOX35_WINDOWS); assertGecko(bd); diff --git a/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java b/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java index e5d53b759d..23a72ee1e5 100644 --- a/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java +++ b/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java @@ -15,18 +15,20 @@ */ package com.vaadin.data.fieldgroup; +import java.beans.IntrospectionException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import com.vaadin.data.Item; import com.vaadin.data.util.BeanItem; +import com.vaadin.data.util.BeanUtil; import com.vaadin.data.validator.BeanValidator; import com.vaadin.ui.Field; public class BeanFieldGroup<T> extends FieldGroup { - private Class<T> beanType; + private final Class<T> beanType; private static Boolean beanValidationImplementationAvailable = null; private final Map<Field<?>, BeanValidator> defaultValidators; @@ -47,17 +49,20 @@ public class BeanFieldGroup<T> extends FieldGroup { * form "fieldName" or "fieldName.subField[.subField2]" but the * method declaration comes from parent. */ - java.lang.reflect.Field f; try { - f = getField(beanType, propertyId.toString()); - return f.getType(); - } catch (SecurityException e) { - throw new BindException("Cannot determine type of propertyId '" - + propertyId + "'.", e); - } catch (NoSuchFieldException e) { + Class<?> type = BeanUtil.getPropertyType(beanType, + propertyId.toString()); + if (type == null) { + throw new BindException( + "Cannot determine type of propertyId '" + + propertyId + + "'. The propertyId was not found in " + + beanType.getName()); + } + return type; + } catch (IntrospectionException e) { throw new BindException("Cannot determine type of propertyId '" - + propertyId + "'. The propertyId was not found in " - + beanType.getName(), e); + + propertyId + "'. Unable to introspect " + beanType, e); } } } @@ -79,32 +84,6 @@ public class BeanFieldGroup<T> extends FieldGroup { return null; } - private static java.lang.reflect.Field getField(Class<?> cls, - String propertyId) throws SecurityException, NoSuchFieldException { - if (propertyId.contains(".")) { - String[] parts = propertyId.split("\\.", 2); - // Get the type of the field in the "cls" class - java.lang.reflect.Field field1 = getField(cls, parts[0]); - // Find the rest from the sub type - return getField(field1.getType(), parts[1]); - } else { - try { - // Try to find the field directly in the given class - java.lang.reflect.Field field1 = cls - .getDeclaredField(propertyId); - return field1; - } catch (NoSuchFieldException e) { - // Try super classes until we reach Object - Class<?> superClass = cls.getSuperclass(); - if (superClass != null && superClass != Object.class) { - return getField(superClass, propertyId); - } else { - throw e; - } - } - } - } - private static String getFieldName(Class<?> cls, String propertyId) throws SecurityException, NoSuchFieldException { for (java.lang.reflect.Field field1 : cls.getDeclaredFields()) { @@ -125,21 +104,29 @@ public class BeanFieldGroup<T> extends FieldGroup { * Helper method for setting the data source directly using a bean. This * method wraps the bean in a {@link BeanItem} and calls * {@link #setItemDataSource(Item)}. + * <p> + * For null values, a null item is passed to + * {@link #setItemDataSource(Item)} to be properly clear fields. * * @param bean * The bean to use as data source. */ public void setItemDataSource(T bean) { - setItemDataSource(new BeanItem(bean)); + if (bean == null) { + setItemDataSource((Item) null); + } else { + setItemDataSource(new BeanItem<T>(bean, beanType)); + } } @Override public void setItemDataSource(Item item) { - if (!(item instanceof BeanItem)) { + if (item == null || (item instanceof BeanItem)) { + super.setItemDataSource(item); + } else { throw new RuntimeException(getClass().getSimpleName() + " only supports BeanItems as item data source"); } - super.setItemDataSource(item); } @Override diff --git a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java index 5a4e877554..c89b94ace9 100644 --- a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java +++ b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java @@ -255,6 +255,9 @@ public class FieldGroup implements Serializable { fieldToPropertyId.put(field, propertyId); propertyIdToField.put(propertyId, field); if (itemDataSource == null) { + // Clear any possible existing binding to clear the field + field.setPropertyDataSource(null); + field.clear(); // Will be bound when data source is set return; } @@ -452,6 +455,56 @@ public class FieldGroup implements Serializable { // Not using buffered mode, nothing to do return; } + + startTransactions(); + + try { + firePreCommitEvent(); + + List<InvalidValueException> invalidValueExceptions = commitFields(); + + if (invalidValueExceptions.isEmpty()) { + firePostCommitEvent(); + commitTransactions(); + } else { + throwInvalidValueException(invalidValueExceptions); + } + } catch (Exception e) { + rollbackTransactions(); + + throw new CommitException("Commit failed", e); + } + + } + + private List<InvalidValueException> commitFields() { + List<InvalidValueException> invalidValueExceptions = new ArrayList<InvalidValueException>(); + + for (Field<?> f : fieldToPropertyId.keySet()) { + try { + f.commit(); + } catch (InvalidValueException e) { + invalidValueExceptions.add(e); + } + } + + return invalidValueExceptions; + } + + private void throwInvalidValueException( + List<InvalidValueException> invalidValueExceptions) { + if (invalidValueExceptions.size() == 1) { + throw invalidValueExceptions.get(0); + } else { + InvalidValueException[] causes = invalidValueExceptions + .toArray(new InvalidValueException[invalidValueExceptions + .size()]); + + throw new InvalidValueException(null, causes); + } + } + + private void startTransactions() throws CommitException { for (Field<?> f : fieldToPropertyId.keySet()) { Property.Transactional<?> property = (Property.Transactional<?>) f .getPropertyDataSource(); @@ -462,33 +515,23 @@ public class FieldGroup implements Serializable { } property.startTransaction(); } - try { - firePreCommitEvent(); - // Commit the field values to the properties - for (Field<?> f : fieldToPropertyId.keySet()) { - f.commit(); - } - firePostCommitEvent(); + } - // Commit the properties - for (Field<?> f : fieldToPropertyId.keySet()) { - ((Property.Transactional<?>) f.getPropertyDataSource()) - .commit(); - } + private void commitTransactions() { + for (Field<?> f : fieldToPropertyId.keySet()) { + ((Property.Transactional<?>) f.getPropertyDataSource()).commit(); + } + } - } catch (Exception e) { - for (Field<?> f : fieldToPropertyId.keySet()) { - try { - ((Property.Transactional<?>) f.getPropertyDataSource()) - .rollback(); - } catch (Exception rollbackException) { - // FIXME: What to do ? - } + private void rollbackTransactions() { + for (Field<?> f : fieldToPropertyId.keySet()) { + try { + ((Property.Transactional<?>) f.getPropertyDataSource()) + .rollback(); + } catch (Exception rollbackException) { + // FIXME: What to do ? } - - throw new CommitException("Commit failed", e); } - } /** diff --git a/server/src/com/vaadin/data/util/AbstractBeanContainer.java b/server/src/com/vaadin/data/util/AbstractBeanContainer.java index adf6313770..fad0934e53 100644 --- a/server/src/com/vaadin/data/util/AbstractBeanContainer.java +++ b/server/src/com/vaadin/data/util/AbstractBeanContainer.java @@ -152,7 +152,7 @@ public abstract class AbstractBeanContainer<IDTYPE, BEANTYPE> extends * A description of the properties found in beans of type {@link #type}. * Determines the property ids that are present in the container. */ - private LinkedHashMap<String, VaadinPropertyDescriptor<BEANTYPE>> model; + private final LinkedHashMap<String, VaadinPropertyDescriptor<BEANTYPE>> model; /** * Constructs a {@code AbstractBeanContainer} for beans of the given type. @@ -178,7 +178,11 @@ public abstract class AbstractBeanContainer<IDTYPE, BEANTYPE> extends */ @Override public Class<?> getType(Object propertyId) { - return model.get(propertyId).getPropertyType(); + VaadinPropertyDescriptor<BEANTYPE> descriptor = model.get(propertyId); + if (descriptor == null) { + return null; + } + return descriptor.getPropertyType(); } /** @@ -876,7 +880,7 @@ public abstract class AbstractBeanContainer<IDTYPE, BEANTYPE> extends model.put(qualifiedPropertyId, pd); model.remove(propertyId); for (BeanItem<BEANTYPE> item : itemIdToItem.values()) { - item.addItemProperty(propertyId, + item.addItemProperty(qualifiedPropertyId, pd.createProperty(item.getBean())); item.removeItemProperty(propertyId); } diff --git a/server/src/com/vaadin/data/util/BeanItem.java b/server/src/com/vaadin/data/util/BeanItem.java index 12d9b23d0a..1be8b70f47 100644 --- a/server/src/com/vaadin/data/util/BeanItem.java +++ b/server/src/com/vaadin/data/util/BeanItem.java @@ -16,12 +16,8 @@ package com.vaadin.data.util; -import java.beans.BeanInfo; -import java.beans.IntrospectionException; -import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; @@ -62,7 +58,30 @@ public class BeanItem<BT> extends PropertysetItem { * */ public BeanItem(BT bean) { - this(bean, getPropertyDescriptors((Class<BT>) bean.getClass())); + this(bean, (Class<BT>) bean.getClass()); + } + + /** + * <p> + * Creates a new instance of <code>BeanItem</code> and adds all properties + * of a Java Bean to it. The properties are identified by their respective + * bean names. + * </p> + * + * <p> + * Note : This version only supports introspectable bean properties and + * their getter and setter methods. Stand-alone <code>is</code> and + * <code>are</code> methods are not supported. + * </p> + * + * @param bean + * the Java Bean to copy properties from. + * @param beanClass + * class of the {@code bean} + * + */ + public BeanItem(BT bean, Class<BT> beanClass) { + this(bean, getPropertyDescriptors(beanClass)); } /** @@ -166,7 +185,8 @@ public class BeanItem<BT> extends PropertysetItem { // Try to introspect, if it fails, we just have an empty Item try { - List<PropertyDescriptor> propertyDescriptors = getBeanPropertyDescriptor(beanClass); + List<PropertyDescriptor> propertyDescriptors = BeanUtil + .getBeanPropertyDescriptor(beanClass); // Add all the bean properties as MethodProperties to this Item // later entries on the list overwrite earlier ones @@ -187,106 +207,6 @@ public class BeanItem<BT> extends PropertysetItem { } /** - * Returns the property descriptors of a class or an interface. - * - * For an interface, superinterfaces are also iterated as Introspector does - * not take them into account (Oracle Java bug 4275879), but in that case, - * both the setter and the getter for a property must be in the same - * interface and should not be overridden in subinterfaces for the discovery - * to work correctly. - * - * For interfaces, the iteration is depth first and the properties of - * superinterfaces are returned before those of their subinterfaces. - * - * @param beanClass - * @return - * @throws IntrospectionException - */ - private static List<PropertyDescriptor> getBeanPropertyDescriptor( - final Class<?> beanClass) throws IntrospectionException { - // Oracle bug 4275879: Introspector does not consider superinterfaces of - // an interface - if (beanClass.isInterface()) { - List<PropertyDescriptor> propertyDescriptors = new ArrayList<PropertyDescriptor>(); - - for (Class<?> cls : beanClass.getInterfaces()) { - propertyDescriptors.addAll(getBeanPropertyDescriptor(cls)); - } - - BeanInfo info = Introspector.getBeanInfo(beanClass); - propertyDescriptors.addAll(getPropertyDescriptors(info)); - - return propertyDescriptors; - } else { - BeanInfo info = Introspector.getBeanInfo(beanClass); - return getPropertyDescriptors(info); - } - } - - // Workaround for Java6 bug JDK-6788525. Do nothing for JDK7+. - private static List<PropertyDescriptor> getPropertyDescriptors( - BeanInfo beanInfo) { - PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors(); - List<PropertyDescriptor> result = new ArrayList<PropertyDescriptor>( - descriptors.length); - for (PropertyDescriptor descriptor : descriptors) { - try { - Method readMethod = getMethodFromBridge(descriptor - .getReadMethod()); - if (readMethod != null) { - Method writeMethod = getMethodFromBridge( - descriptor.getWriteMethod(), - readMethod.getReturnType()); - if (writeMethod == null) { - writeMethod = descriptor.getWriteMethod(); - } - PropertyDescriptor descr = new PropertyDescriptor( - descriptor.getName(), readMethod, writeMethod); - result.add(descr); - } else { - result.add(descriptor); - } - } catch (SecurityException ignore) { - // handle next descriptor - } catch (IntrospectionException e) { - result.add(descriptor); - } - } - return result; - } - - /** - * Return not bridged method for bridge {@code bridgeMethod} method. If - * method {@code bridgeMethod} is not bridge method then return null. - */ - private static Method getMethodFromBridge(Method bridgeMethod) - throws SecurityException { - if (bridgeMethod == null) { - return null; - } - return getMethodFromBridge(bridgeMethod, - bridgeMethod.getParameterTypes()); - } - - /** - * Return not bridged method for bridge {@code bridgeMethod} method and - * declared {@code paramTypes}. If method {@code bridgeMethod} is not bridge - * method then return null. - */ - private static Method getMethodFromBridge(Method bridgeMethod, - Class<?>... paramTypes) throws SecurityException { - if (bridgeMethod == null || !bridgeMethod.isBridge()) { - return null; - } - try { - return bridgeMethod.getDeclaringClass().getMethod( - bridgeMethod.getName(), paramTypes); - } catch (NoSuchMethodException e) { - return null; - } - } - - /** * Expands nested bean properties by replacing a top-level property with * some or all of its sub-properties. The expansion is not recursive. * diff --git a/server/src/com/vaadin/data/util/BeanUtil.java b/server/src/com/vaadin/data/util/BeanUtil.java new file mode 100644 index 0000000000..e2f85a765c --- /dev/null +++ b/server/src/com/vaadin/data/util/BeanUtil.java @@ -0,0 +1,177 @@ +/* + * 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.data.util; + +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.io.Serializable; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +/** + * Utility class for Java Beans information access. + * + * @author Vaadin Ltd + */ +public final class BeanUtil implements Serializable { + // Prevent instantiation of util class + private BeanUtil() { + } + + /** + * Returns the property descriptors of a class or an interface. + * + * For an interface, superinterfaces are also iterated as Introspector does + * not take them into account (Oracle Java bug 4275879), but in that case, + * both the setter and the getter for a property must be in the same + * interface and should not be overridden in subinterfaces for the discovery + * to work correctly. + * + * NOTE : This utility method relies on introspection (and returns + * PropertyDescriptor) which is a part of java.beans package. The latter + * package could require bigger JDK in the future (with Java 9+). So it may + * be changed in the future. + * + * For interfaces, the iteration is depth first and the properties of + * superinterfaces are returned before those of their subinterfaces. + * + * @param beanClass + * @return + * @throws IntrospectionException + */ + public static List<PropertyDescriptor> getBeanPropertyDescriptor( + final Class<?> beanClass) throws IntrospectionException { + // Oracle bug 4275879: Introspector does not consider superinterfaces of + // an interface + if (beanClass.isInterface()) { + List<PropertyDescriptor> propertyDescriptors = new ArrayList<PropertyDescriptor>(); + + for (Class<?> cls : beanClass.getInterfaces()) { + propertyDescriptors.addAll(getBeanPropertyDescriptor(cls)); + } + + BeanInfo info = Introspector.getBeanInfo(beanClass); + propertyDescriptors.addAll(getPropertyDescriptors(info)); + + return propertyDescriptors; + } else { + BeanInfo info = Introspector.getBeanInfo(beanClass); + return getPropertyDescriptors(info); + } + } + + /** + * Returns {@code propertyId} class for property declared in {@code clazz}. + * Property could be of form "property.subProperty[.subProperty2]" i.e. + * refer to some nested property. + * + * @param clazz + * class where property is declared + * @param propertyId + * property of form "property" or + * "property.subProperty[.subProperty2]" + * @return class of the property + * @throws IntrospectionException + */ + public static Class<?> getPropertyType(Class<?> clazz, String propertyId) + throws IntrospectionException { + if (propertyId.contains(".")) { + String[] parts = propertyId.split("\\.", 2); + // Get the type of the field in the "cls" class + Class<?> propertyBean = getPropertyType(clazz, parts[0]); + // Find the rest from the sub type + return getPropertyType(propertyBean, parts[1]); + } else { + List<PropertyDescriptor> descriptors = getBeanPropertyDescriptor(clazz); + + for (PropertyDescriptor descriptor : descriptors) { + final Method getMethod = descriptor.getReadMethod(); + if (descriptor.getName().equals(propertyId) + && getMethod != null + && getMethod.getDeclaringClass() != Object.class) { + return descriptor.getPropertyType(); + } + } + return null; + } + } + + // Workaround for Java6 bug JDK-6788525. Do nothing for JDK7+. + private static List<PropertyDescriptor> getPropertyDescriptors( + BeanInfo beanInfo) { + PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors(); + List<PropertyDescriptor> result = new ArrayList<PropertyDescriptor>( + descriptors.length); + for (PropertyDescriptor descriptor : descriptors) { + try { + Method readMethod = getMethodFromBridge(descriptor + .getReadMethod()); + if (readMethod != null) { + Method writeMethod = getMethodFromBridge( + descriptor.getWriteMethod(), + readMethod.getReturnType()); + if (writeMethod == null) { + writeMethod = descriptor.getWriteMethod(); + } + PropertyDescriptor descr = new PropertyDescriptor( + descriptor.getName(), readMethod, writeMethod); + result.add(descr); + } else { + result.add(descriptor); + } + } catch (SecurityException ignore) { + // handle next descriptor + } catch (IntrospectionException e) { + result.add(descriptor); + } + } + return result; + } + + /** + * Return declared method for which {@code bridgeMethod} is generated. If + * {@code bridgeMethod} is not a bridge method then return null. + */ + private static Method getMethodFromBridge(Method bridgeMethod) + throws SecurityException { + if (bridgeMethod == null) { + return null; + } + return getMethodFromBridge(bridgeMethod, + bridgeMethod.getParameterTypes()); + } + + /** + * Return declared method for which {@code bridgeMethod} is generated using + * its {@code paramTypes}. If {@code bridgeMethod} is not a bridge method + * then return null. + */ + private static Method getMethodFromBridge(Method bridgeMethod, + Class<?>... paramTypes) throws SecurityException { + if (bridgeMethod == null || !bridgeMethod.isBridge()) { + return null; + } + try { + return bridgeMethod.getDeclaringClass().getMethod( + bridgeMethod.getName(), paramTypes); + } catch (NoSuchMethodException e) { + return null; + } + } +} diff --git a/server/src/com/vaadin/data/util/MethodProperty.java b/server/src/com/vaadin/data/util/MethodProperty.java index 5e6b731571..853f68b711 100644 --- a/server/src/com/vaadin/data/util/MethodProperty.java +++ b/server/src/com/vaadin/data/util/MethodProperty.java @@ -132,7 +132,7 @@ public class MethodProperty<T> extends AbstractProperty<T> { setArguments(getArgs, setArgs, setArgumentIndex); String name = (String) in.readObject(); Class<?>[] paramTypes = SerializerHelper.readClassArray(in); - if (name != null) { + if (instance != null && name != null) { setMethod = instance.getClass().getMethod(name, paramTypes); } else { setMethod = null; @@ -140,7 +140,7 @@ public class MethodProperty<T> extends AbstractProperty<T> { name = (String) in.readObject(); paramTypes = SerializerHelper.readClassArray(in); - if (name != null) { + if (instance != null && name != null) { getMethod = instance.getClass().getMethod(name, paramTypes); } else { getMethod = null; @@ -589,7 +589,11 @@ public class MethodProperty<T> extends AbstractProperty<T> { @Override public T getValue() { try { - return (T) getMethod.invoke(instance, getArgs); + if (instance == null) { + return null; + } else { + return (T) getMethod.invoke(instance, getArgs); + } } catch (final Throwable e) { throw new MethodException(this, e); } diff --git a/server/src/com/vaadin/data/util/converter/AbstractStringToNumberConverter.java b/server/src/com/vaadin/data/util/converter/AbstractStringToNumberConverter.java index 9054f258c7..81f1a85f89 100644 --- a/server/src/com/vaadin/data/util/converter/AbstractStringToNumberConverter.java +++ b/server/src/com/vaadin/data/util/converter/AbstractStringToNumberConverter.java @@ -88,6 +88,7 @@ public abstract class AbstractStringToNumberConverter<T> implements // Convert "" to null return null; } + return parsedValue; } diff --git a/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java b/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java index 26613c5d02..3a1f1a4252 100644 --- a/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java +++ b/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java @@ -17,6 +17,7 @@ package com.vaadin.data.util.converter; import java.math.BigDecimal; +import java.math.BigInteger; import java.util.Date; import java.util.logging.Logger; @@ -112,6 +113,12 @@ public class DefaultConverterFactory implements ConverterFactory { return new StringToDateConverter(); } else if (Enum.class.isAssignableFrom(sourceType)) { return new StringToEnumConverter(); + } else if (BigInteger.class.isAssignableFrom(sourceType)) { + return new StringToBigIntegerConverter(); + } else if (Short.class.isAssignableFrom(sourceType)) { + return new StringToShortConverter(); + } else if (Byte.class.isAssignableFrom(sourceType)) { + return new StringToByteConverter(); } else { return null; } diff --git a/server/src/com/vaadin/data/util/converter/StringToBigIntegerConverter.java b/server/src/com/vaadin/data/util/converter/StringToBigIntegerConverter.java index 1e830c1fd2..d176ac2e0d 100644 --- a/server/src/com/vaadin/data/util/converter/StringToBigIntegerConverter.java +++ b/server/src/com/vaadin/data/util/converter/StringToBigIntegerConverter.java @@ -15,6 +15,7 @@ */ package com.vaadin.data.util.converter; +import java.math.BigDecimal; import java.math.BigInteger; import java.text.DecimalFormat; import java.text.NumberFormat; @@ -32,7 +33,7 @@ import java.util.Locale; * </p> * * @author Vaadin Ltd - * @since 7.3.1 + * @since */ public class StringToBigIntegerConverter extends AbstractStringToNumberConverter<BigInteger> { @@ -41,7 +42,7 @@ public class StringToBigIntegerConverter extends protected NumberFormat getFormat(Locale locale) { NumberFormat numberFormat = super.getFormat(locale); if (numberFormat instanceof DecimalFormat) { - ((DecimalFormat) numberFormat).setParseIntegerOnly(true); + ((DecimalFormat) numberFormat).setParseBigDecimal(true); } return numberFormat; @@ -51,7 +52,11 @@ public class StringToBigIntegerConverter extends public BigInteger convertToModel(String value, Class<? extends BigInteger> targetType, Locale locale) throws com.vaadin.data.util.converter.Converter.ConversionException { - return (BigInteger) convertToNumber(value, BigInteger.class, locale); + + BigDecimal bigDecimalValue = (BigDecimal) convertToNumber(value, + BigDecimal.class, locale); + + return (bigDecimalValue != null) ? bigDecimalValue.toBigInteger() : null; } @Override diff --git a/server/src/com/vaadin/data/util/converter/StringToByteConverter.java b/server/src/com/vaadin/data/util/converter/StringToByteConverter.java index b14182dc3f..26f52d108a 100644 --- a/server/src/com/vaadin/data/util/converter/StringToByteConverter.java +++ b/server/src/com/vaadin/data/util/converter/StringToByteConverter.java @@ -28,7 +28,7 @@ import java.util.Locale; * </p> * * @author Vaadin Ltd - * @since 7.3.1 + * @since */ public class StringToByteConverter extends AbstractStringToNumberConverter<Byte> { diff --git a/server/src/com/vaadin/data/util/converter/StringToEnumConverter.java b/server/src/com/vaadin/data/util/converter/StringToEnumConverter.java index a1328d831c..e91dd2a303 100644 --- a/server/src/com/vaadin/data/util/converter/StringToEnumConverter.java +++ b/server/src/com/vaadin/data/util/converter/StringToEnumConverter.java @@ -34,9 +34,31 @@ public class StringToEnumConverter implements Converter<String, Enum> { @Override public Enum convertToModel(String value, Class<? extends Enum> targetType, Locale locale) throws ConversionException { - if (value == null) { + if (value == null || value.trim().equals("")) { return null; } + + return stringToEnum(value, targetType, locale); + } + + /** + * Converts the given string to the given enum type using the given locale + * <p> + * Compatible with {@link #enumToString(Enum, Locale)} + * + * @param value + * The string value to convert + * @param enumType + * The type of enum to create + * @param locale + * The locale to use for conversion. If null, the JVM default + * locale will be used + * @return The enum which matches the given string + * @throws ConversionException + * if the conversion fails + */ + public static <T extends Enum<T>> T stringToEnum(String value, + Class<T> enumType, Locale locale) throws ConversionException { if (locale == null) { locale = Locale.getDefault(); } @@ -45,31 +67,41 @@ public class StringToEnumConverter implements Converter<String, Enum> { // Foo bar -> FOO_BAR String result = value.replace(" ", "_").toUpperCase(locale); try { - return Enum.valueOf(targetType, result); - } catch (IllegalArgumentException ee) { + return Enum.valueOf(enumType, result); + } catch (Exception ee) { // There was no match. Try to compare the available values to see if // the constant is using something else than all upper case - - EnumSet<?> set = EnumSet.allOf(targetType); - for (Enum e : set) { - if (e.name().toUpperCase(locale).equals(result)) { - return e; + try { + EnumSet<T> set = EnumSet.allOf(enumType); + for (T e : set) { + if (e.name().toUpperCase(locale).equals(result)) { + return e; + } } + } catch (Exception e) { } - // Fallback did not work either, re-throw original exception so user - // knows what went wrong + // Fallback did not work either, re-throw original exception so + // user knows what went wrong throw new ConversionException(ee); } } - @Override - public String convertToPresentation(Enum value, - Class<? extends String> targetType, Locale locale) - throws ConversionException { - if (value == null) { - return null; - } + /** + * Converts the given enum to a human readable string using the given locale + * <p> + * Compatible with {@link #stringToEnum(String, Class, Locale)} + * + * @param value + * The enum value to convert + * @param locale + * The locale to use for conversion. If null, the JVM default + * locale will be used + * @return A human readable string based on the enum + * @throws ConversionException + * if the conversion fails + */ + public static String enumToString(Enum<?> value, Locale locale) { if (locale == null) { locale = Locale.getDefault(); } @@ -80,11 +112,21 @@ public class StringToEnumConverter implements Converter<String, Enum> { // _FOO -> _foo String result = enumString.substring(0, 1).toUpperCase(locale); result += enumString.substring(1).toLowerCase(locale).replace('_', ' '); - return result; } @Override + public String convertToPresentation(Enum value, + Class<? extends String> targetType, Locale locale) + throws ConversionException { + if (value == null) { + return null; + } + + return enumToString(value, locale); + } + + @Override public Class<Enum> getModelType() { return Enum.class; } diff --git a/server/src/com/vaadin/data/util/converter/StringToShortConverter.java b/server/src/com/vaadin/data/util/converter/StringToShortConverter.java index 3761d11227..4ee085286f 100644 --- a/server/src/com/vaadin/data/util/converter/StringToShortConverter.java +++ b/server/src/com/vaadin/data/util/converter/StringToShortConverter.java @@ -28,7 +28,7 @@ import java.util.Locale; * </p> * * @author Vaadin Ltd - * @since 7.3.1 + * @since */ public class StringToShortConverter extends AbstractStringToNumberConverter<Short> { diff --git a/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java b/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java index 683140d279..c0c660c084 100644 --- a/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java +++ b/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java @@ -652,7 +652,6 @@ public class SQLContainer implements Container, Container.Filterable, if (cachedItems.isEmpty()) { getPage(); } - int size = size(); // this protects against infinite looping int counter = 0; int oldIndex; @@ -1020,18 +1019,20 @@ public class SQLContainer implements Container, Container.Filterable, } /* Perform buffered modifications */ for (RowItem item : modifiedItems) { - if (queryDelegate.storeRow(item) > 0) { - /* - * Also reset the modified state in the item in case it is - * reused e.g. in a form. - */ - item.commit(); - } else { - queryDelegate.rollback(); - refresh(); - throw new ConcurrentModificationException( - "Item with the ID '" + item.getId() - + "' has been externally modified."); + if (!removedItems.containsKey(item.getId())) { + if (queryDelegate.storeRow(item) > 0) { + /* + * Also reset the modified state in the item in case it + * is reused e.g. in a form. + */ + item.commit(); + } else { + queryDelegate.rollback(); + refresh(); + throw new ConcurrentModificationException( + "Item with the ID '" + item.getId() + + "' has been externally modified."); + } } } /* Perform buffered additions */ diff --git a/server/src/com/vaadin/data/util/sqlcontainer/query/generator/DefaultSQLGenerator.java b/server/src/com/vaadin/data/util/sqlcontainer/query/generator/DefaultSQLGenerator.java index 84dfe9b865..21a486a017 100644 --- a/server/src/com/vaadin/data/util/sqlcontainer/query/generator/DefaultSQLGenerator.java +++ b/server/src/com/vaadin/data/util/sqlcontainer/query/generator/DefaultSQLGenerator.java @@ -262,6 +262,12 @@ public class DefaultSQLGenerator implements SQLGenerator { count++; } if (versionColumn != null) { + if(!item.getItemPropertyIds().contains(versionColumn)) { + throw new IllegalArgumentException(String.format( + "Table '%s' does not contain version column '%s'.", + tableName, versionColumn)); + } + query.append(String.format(" AND %s = ?", QueryBuilder.quote(versionColumn))); sh.addParameterValue( diff --git a/server/src/com/vaadin/navigator/Navigator.java b/server/src/com/vaadin/navigator/Navigator.java index 80dad2244e..591f73dc75 100644 --- a/server/src/com/vaadin/navigator/Navigator.java +++ b/server/src/com/vaadin/navigator/Navigator.java @@ -371,6 +371,7 @@ public class Navigator implements Serializable { private View currentView = null; private List<ViewChangeListener> listeners = new LinkedList<ViewChangeListener>(); private List<ViewProvider> providers = new LinkedList<ViewProvider>(); + private String currentNavigationState = null; private ViewProvider errorProvider; /** @@ -551,6 +552,11 @@ public class Navigator implements Serializable { ViewChangeEvent event = new ViewChangeEvent(this, currentView, view, viewName, parameters); if (!fireBeforeViewChange(event)) { + // #10901. Revert URL to previous state if back-button navigation + // was canceled + if (currentNavigationState != null) { + getStateManager().setState(currentNavigationState); + } return; } @@ -561,6 +567,7 @@ public class Navigator implements Serializable { } if (!navigationState.equals(getStateManager().getState())) { getStateManager().setState(navigationState); + currentNavigationState = navigationState; } } diff --git a/server/src/com/vaadin/server/BootstrapHandler.java b/server/src/com/vaadin/server/BootstrapHandler.java index f0666f63fc..c34e986fce 100644 --- a/server/src/com/vaadin/server/BootstrapHandler.java +++ b/server/src/com/vaadin/server/BootstrapHandler.java @@ -469,6 +469,8 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler { JsonObject versionInfo = Json.createObject(); versionInfo.put("vaadinVersion", Version.getFullVersion()); + versionInfo.put("atmosphereVersion", + org.atmosphere.util.Version.getRawVersion()); appConfig.put("versionInfo", versionInfo); appConfig.put("widgetset", context.getWidgetsetName()); diff --git a/server/src/com/vaadin/server/FileResource.java b/server/src/com/vaadin/server/FileResource.java index de14e2f0f2..b32905f972 100644 --- a/server/src/com/vaadin/server/FileResource.java +++ b/server/src/com/vaadin/server/FileResource.java @@ -57,6 +57,9 @@ public class FileResource implements ConnectorResource { * the file that should be served. */ public FileResource(File sourceFile) { + if (sourceFile == null) { + throw new IllegalArgumentException("File cannot be null"); + } setSourceFile(sourceFile); } diff --git a/server/src/com/vaadin/server/VaadinService.java b/server/src/com/vaadin/server/VaadinService.java index fb93a44d37..36d6910a7a 100644 --- a/server/src/com/vaadin/server/VaadinService.java +++ b/server/src/com/vaadin/server/VaadinService.java @@ -703,12 +703,12 @@ public abstract class VaadinService implements Serializable { final boolean closeApplication = hasParameter(request, URL_PARAMETER_CLOSE_APPLICATION); - if (restartApplication) { - closeSession(session, request.getWrappedSession(false)); - return createAndRegisterSession(request); - } else if (closeApplication) { + if (closeApplication) { closeSession(session, request.getWrappedSession(false)); return null; + } else if (restartApplication) { + closeSession(session, request.getWrappedSession(false)); + return createAndRegisterSession(request); } else { return session; } diff --git a/server/src/com/vaadin/server/VaadinServlet.java b/server/src/com/vaadin/server/VaadinServlet.java index 4656f9a672..d1242676da 100644 --- a/server/src/com/vaadin/server/VaadinServlet.java +++ b/server/src/com/vaadin/server/VaadinServlet.java @@ -573,8 +573,8 @@ public class VaadinServlet extends HttpServlet implements Constants { /** * A helper method to strip away characters that might somehow be used for - * XSS attacs. Leaves at least alphanumeric characters intact. Also removes - * eg. ( and ), so values should be safe in javascript too. + * XSS attacks. Leaves at least alphanumeric characters intact. Also removes + * e.g. '(' and ')', so values should be safe in javascript too. * * @param themeName * @return @@ -583,7 +583,7 @@ public class VaadinServlet extends HttpServlet implements Constants { * version */ @Deprecated - protected static String stripSpecialChars(String themeName) { + public static String stripSpecialChars(String themeName) { StringBuilder sb = new StringBuilder(); char[] charArray = themeName.toCharArray(); for (int i = 0; i < charArray.length; i++) { @@ -704,6 +704,15 @@ public class VaadinServlet extends HttpServlet implements Constants { return; } + String cacheControl = "public, max-age=0, must-revalidate"; + int resourceCacheTime = getCacheTime(filename); + if (resourceCacheTime > 0) { + cacheControl = "max-age=" + String.valueOf(resourceCacheTime); + } + response.setHeader("Cache-Control", cacheControl); + response.setDateHeader("Expires", System.currentTimeMillis() + + (resourceCacheTime * 1000)); + // Find the modification timestamp long lastModifiedTime = 0; URLConnection connection = null; @@ -714,6 +723,7 @@ public class VaadinServlet extends HttpServlet implements Constants { // are not returned by the browser in the "If-Modified-Since" // header). lastModifiedTime = lastModifiedTime - lastModifiedTime % 1000; + response.setDateHeader("Last-Modified", lastModifiedTime); if (browserHasNewestVersion(request, lastModifiedTime)) { response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); @@ -748,18 +758,6 @@ public class VaadinServlet extends HttpServlet implements Constants { response.setContentType(mimetype); } - // Provide modification timestamp to the browser if it is known. - if (lastModifiedTime > 0) { - response.setDateHeader("Last-Modified", lastModifiedTime); - - String cacheControl = "public, max-age=0, must-revalidate"; - int resourceCacheTime = getCacheTime(filename); - if (resourceCacheTime > 0) { - cacheControl = "max-age=" + String.valueOf(resourceCacheTime); - } - response.setHeader("Cache-Control", cacheControl); - } - writeStaticResourceResponse(request, response, resourceUrl); } diff --git a/server/src/com/vaadin/server/communication/UIInitHandler.java b/server/src/com/vaadin/server/communication/UIInitHandler.java index 356ad25219..1216d2b689 100644 --- a/server/src/com/vaadin/server/communication/UIInitHandler.java +++ b/server/src/com/vaadin/server/communication/UIInitHandler.java @@ -17,7 +17,7 @@ package com.vaadin.server.communication; import java.io.IOException; -import java.io.OutputStreamWriter; +import java.io.OutputStream; import java.io.StringWriter; import java.util.List; import java.util.logging.Level; @@ -65,8 +65,6 @@ public abstract class UIInitHandler extends SynchronizedRequestHandler { @Override public boolean synchronizedHandleRequest(VaadinSession session, VaadinRequest request, VaadinResponse response) throws IOException { - StringWriter stringWriter = new StringWriter(); - try { assert UI.getCurrent() == null; @@ -82,14 +80,10 @@ public abstract class UIInitHandler extends SynchronizedRequestHandler { String initialUIDL = getInitialUidl(request, uI); params.put("uidl", initialUIDL); - stringWriter.write(JsonUtil.stringify(params)); + return commitJsonResponse(request, response, JsonUtil.stringify(params)); } catch (JsonException e) { throw new IOException("Error producing initial UIDL", e); - } finally { - stringWriter.close(); } - - return commitJsonResponse(request, response, stringWriter.toString()); } /** @@ -116,18 +110,13 @@ public abstract class UIInitHandler extends SynchronizedRequestHandler { // iOS 6 Safari requires this (#9732) response.setHeader("Cache-Control", "no-cache"); - // NOTE! GateIn requires, for some weird reason, getOutputStream - // to be used instead of getWriter() (it seems to interpret - // application/json as a binary content type) - OutputStreamWriter outputWriter = new OutputStreamWriter( - response.getOutputStream(), "UTF-8"); - try { - outputWriter.write(json); - // NOTE GateIn requires the buffers to be flushed to work - outputWriter.flush(); - } finally { - outputWriter.close(); - } + byte[] b = json.getBytes("UTF-8"); + response.setHeader("Content-Length", String.valueOf(b.length)); + + OutputStream outputStream = response.getOutputStream(); + outputStream.write(b); + // NOTE GateIn requires the buffers to be flushed to work + outputStream.flush(); return true; } diff --git a/server/src/com/vaadin/ui/AbsoluteLayout.java b/server/src/com/vaadin/ui/AbsoluteLayout.java index 27ddb86dad..39f00901fc 100644 --- a/server/src/com/vaadin/ui/AbsoluteLayout.java +++ b/server/src/com/vaadin/ui/AbsoluteLayout.java @@ -166,7 +166,6 @@ public class AbsoluteLayout extends AbstractLayout implements internalRemoveComponent(c); throw e; } - markAsDirty(); } /** @@ -210,7 +209,6 @@ public class AbsoluteLayout extends AbstractLayout implements public void removeComponent(Component c) { internalRemoveComponent(c); super.removeComponent(c); - markAsDirty(); } /** diff --git a/server/src/com/vaadin/ui/AbstractComponentContainer.java b/server/src/com/vaadin/ui/AbstractComponentContainer.java index e70b0fa0ce..1095331602 100644 --- a/server/src/com/vaadin/ui/AbstractComponentContainer.java +++ b/server/src/com/vaadin/ui/AbstractComponentContainer.java @@ -209,6 +209,7 @@ public abstract class AbstractComponentContainer extends AbstractComponent c.setParent(this); fireComponentAttachEvent(c); + markAsDirty(); } /** @@ -223,6 +224,7 @@ public abstract class AbstractComponentContainer extends AbstractComponent if (equals(c.getParent())) { c.setParent(null); fireComponentDetachEvent(c); + markAsDirty(); } } diff --git a/server/src/com/vaadin/ui/AbstractField.java b/server/src/com/vaadin/ui/AbstractField.java index 6d4b5ff2d7..9b9c7efd86 100644 --- a/server/src/com/vaadin/ui/AbstractField.java +++ b/server/src/com/vaadin/ui/AbstractField.java @@ -1508,25 +1508,12 @@ public abstract class AbstractField<T> extends AbstractComponent implements markAsDirty(); } - /** - * Is the field empty? - * - * In general, "empty" state is same as null. As an exception, TextField - * also treats empty string as "empty". - */ - protected boolean isEmpty() { + @Override + public boolean isEmpty() { return (getFieldValue() == null); } - /** - * Clear the value of the field. - * <p> - * The field value is typically reset to the initial value of the field but - * this is not mandatory. Calling {@link #isEmpty()} on a cleared field must - * always returns true. - * - * @since - */ + @Override public void clear() { setValue(null); } diff --git a/server/src/com/vaadin/ui/AbstractSelect.java b/server/src/com/vaadin/ui/AbstractSelect.java index 2c4dd5be5d..1a3eeb88a3 100644 --- a/server/src/com/vaadin/ui/AbstractSelect.java +++ b/server/src/com/vaadin/ui/AbstractSelect.java @@ -33,6 +33,8 @@ import com.vaadin.data.Container; import com.vaadin.data.Item; import com.vaadin.data.Property; import com.vaadin.data.util.IndexedContainer; +import com.vaadin.data.util.converter.Converter; +import com.vaadin.data.util.converter.ConverterUtil; import com.vaadin.event.DataBoundTransferable; import com.vaadin.event.Transferable; import com.vaadin.event.dd.DragAndDropEvent; @@ -1181,7 +1183,7 @@ public abstract class AbstractSelect extends AbstractField<Object> implements switch (getItemCaptionMode()) { case ID: - caption = itemId.toString(); + caption = idToCaption(itemId); break; case INDEX: @@ -1207,7 +1209,7 @@ public abstract class AbstractSelect extends AbstractField<Object> implements case EXPLICIT_DEFAULTS_ID: caption = itemCaptions.get(itemId); if (caption == null) { - caption = itemId.toString(); + caption = idToCaption(itemId); } break; @@ -1227,6 +1229,17 @@ public abstract class AbstractSelect extends AbstractField<Object> implements return caption != null ? caption : ""; } + private String idToCaption(Object itemId) { + try { + Converter<String, Object> c = (Converter<String, Object>) ConverterUtil + .getConverter(String.class, itemId.getClass(), getSession()); + return ConverterUtil.convertFromModel(itemId, String.class, c, + getLocale()); + } catch (Exception e) { + return itemId.toString(); + } + } + /** * Sets tqhe icon for an item. * @@ -1782,7 +1795,7 @@ public abstract class AbstractSelect extends AbstractField<Object> implements * @see AbstractField#isEmpty(). */ @Override - protected boolean isEmpty() { + public boolean isEmpty() { if (!multiSelect) { return super.isEmpty(); } else { diff --git a/server/src/com/vaadin/ui/AbstractSplitPanel.java b/server/src/com/vaadin/ui/AbstractSplitPanel.java index 29dbadecc4..e366c33593 100644 --- a/server/src/com/vaadin/ui/AbstractSplitPanel.java +++ b/server/src/com/vaadin/ui/AbstractSplitPanel.java @@ -221,7 +221,6 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer { } else if (c == getSecondComponent()) { getState().secondChild = null; } - markAsDirty(); } /* @@ -263,7 +262,6 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer { } else if (oldComponent == getSecondComponent()) { setSecondComponent(newComponent); } - markAsDirty(); } /** @@ -349,12 +347,26 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer { * Returns the unit of position of the splitter * * @return unit of position of the splitter + * @see #setSplitPosition(float, Unit) */ public Unit getSplitPositionUnit() { return posUnit; } /** + * Is the split position reversed. By default the split position is measured + * by the first region, but if split position is reversed the measuring is + * done by the second region instead. + * + * @since + * @return {@code true} if reversed, {@code false} otherwise. + * @see #setSplitPosition(float, boolean) + */ + public boolean isSplitPositionReversed() { + return getSplitterState(false).positionReversed; + } + + /** * Sets the minimum split position to the given position and unit. If the * split position is reversed, maximum and minimum are also reversed. * diff --git a/server/src/com/vaadin/ui/AbstractTextField.java b/server/src/com/vaadin/ui/AbstractTextField.java index adeb1cb69f..93025ac0fd 100644 --- a/server/src/com/vaadin/ui/AbstractTextField.java +++ b/server/src/com/vaadin/ui/AbstractTextField.java @@ -323,7 +323,7 @@ public abstract class AbstractTextField extends AbstractField<String> implements } @Override - protected boolean isEmpty() { + public boolean isEmpty() { return super.isEmpty() || getValue().length() == 0; } diff --git a/server/src/com/vaadin/ui/ComboBox.java b/server/src/com/vaadin/ui/ComboBox.java index c2b80fae35..4af93113f9 100644 --- a/server/src/com/vaadin/ui/ComboBox.java +++ b/server/src/com/vaadin/ui/ComboBox.java @@ -622,7 +622,7 @@ public class ComboBox extends AbstractSelect implements if (caption == null || caption.equals("")) { continue; } else { - caption = caption.toLowerCase(); + caption = caption.toLowerCase(getLocale()); } switch (filteringMode) { case CONTAINS: @@ -682,7 +682,7 @@ public class ComboBox extends AbstractSelect implements currentPage = ((Integer) variables.get("page")).intValue(); filterstring = newFilter; if (filterstring != null) { - filterstring = filterstring.toLowerCase(); + filterstring = filterstring.toLowerCase(getLocale()); } requestRepaint(); } else if (isNewItemsAllowed()) { diff --git a/server/src/com/vaadin/ui/CssLayout.java b/server/src/com/vaadin/ui/CssLayout.java index 9a4da009e9..f3ae6c0695 100644 --- a/server/src/com/vaadin/ui/CssLayout.java +++ b/server/src/com/vaadin/ui/CssLayout.java @@ -121,7 +121,6 @@ public class CssLayout extends AbstractLayout implements LayoutClickNotifier { components.add(c); try { super.addComponent(c); - markAsDirty(); } catch (IllegalArgumentException e) { components.remove(c); throw e; @@ -144,7 +143,6 @@ public class CssLayout extends AbstractLayout implements LayoutClickNotifier { components.addFirst(c); try { super.addComponent(c); - markAsDirty(); } catch (IllegalArgumentException e) { components.remove(c); throw e; @@ -173,7 +171,6 @@ public class CssLayout extends AbstractLayout implements LayoutClickNotifier { components.add(index, c); try { super.addComponent(c); - markAsDirty(); } catch (IllegalArgumentException e) { components.remove(c); throw e; @@ -190,7 +187,6 @@ public class CssLayout extends AbstractLayout implements LayoutClickNotifier { public void removeComponent(Component c) { components.remove(c); super.removeComponent(c); - markAsDirty(); } /** diff --git a/server/src/com/vaadin/ui/CustomLayout.java b/server/src/com/vaadin/ui/CustomLayout.java index f4fe7fa66c..a9c266b0b9 100644 --- a/server/src/com/vaadin/ui/CustomLayout.java +++ b/server/src/com/vaadin/ui/CustomLayout.java @@ -144,8 +144,8 @@ public class CustomLayout extends AbstractLayout implements LegacyComponent { } slots.put(location, c); getState().childLocations.put(c, location); - c.setParent(this); - fireComponentAttachEvent(c); + + super.addComponent(c); } /** diff --git a/server/src/com/vaadin/ui/DateField.java b/server/src/com/vaadin/ui/DateField.java index 030bd5f6c2..3d683f4902 100644 --- a/server/src/com/vaadin/ui/DateField.java +++ b/server/src/com/vaadin/ui/DateField.java @@ -316,10 +316,11 @@ public class DateField extends AbstractField<Date> implements throw new IllegalStateException( "startDate cannot be later than endDate"); } - getState().rangeStart = startDate; - // rangeStart = startDate; - // This has to be done to correct for the resolution - // updateRangeState(); + + // Create a defensive copy against issues when using java.sql.Date (and + // also against mutable Date). + getState().rangeStart = startDate != null ? new Date( + startDate.getTime()) : null; updateRangeValidator(); } @@ -436,8 +437,11 @@ public class DateField extends AbstractField<Date> implements throw new IllegalStateException( "endDate cannot be earlier than startDate"); } - // rangeEnd = endDate; - getState().rangeEnd = endDate; + + // Create a defensive copy against issues when using java.sql.Date (and + // also against mutable Date). + getState().rangeEnd = endDate != null ? new Date(endDate.getTime()) + : null; updateRangeValidator(); } diff --git a/server/src/com/vaadin/ui/Field.java b/server/src/com/vaadin/ui/Field.java index f191e1bdd7..6dee4de6cb 100644 --- a/server/src/com/vaadin/ui/Field.java +++ b/server/src/com/vaadin/ui/Field.java @@ -113,4 +113,26 @@ public interface Field<T> extends Component, BufferedValidatable, Property<T>, return (Property) getSource(); } } + + /** + * Is the field empty? + * + * In general, "empty" state is same as null. As an exception, TextField + * also treats empty string as "empty". + * + * @since + * @return true if the field is empty, false otherwise + */ + public boolean isEmpty(); + + /** + * Clears the value of the field. + * <p> + * The field value is typically reset to the initial value of the field. + * Calling {@link #isEmpty()} on a cleared field must always returns true. + * + * @since + */ + public void clear(); + } diff --git a/server/src/com/vaadin/ui/Form.java b/server/src/com/vaadin/ui/Form.java index 48239b09e3..45532756e5 100644 --- a/server/src/com/vaadin/ui/Form.java +++ b/server/src/com/vaadin/ui/Form.java @@ -1186,9 +1186,14 @@ public class Form extends AbstractField<Object> implements Item.Editor, } } - /** Form is empty if all of its fields are empty. */ + /** + * {@inheritDoc} + * <p> + * A Form is empty if all of its fields are empty. + * + */ @Override - protected boolean isEmpty() { + public boolean isEmpty() { for (Iterator<Field<?>> i = fields.values().iterator(); i.hasNext();) { Field<?> f = i.next(); diff --git a/server/src/com/vaadin/ui/GridLayout.java b/server/src/com/vaadin/ui/GridLayout.java index 0dd16a03e7..96854c5b1b 100644 --- a/server/src/com/vaadin/ui/GridLayout.java +++ b/server/src/com/vaadin/ui/GridLayout.java @@ -255,8 +255,6 @@ public class GridLayout extends AbstractLayout implements cursorY = row1; } } - - markAsDirty(); } /** @@ -390,7 +388,6 @@ public class GridLayout extends AbstractLayout implements getState().childData.remove(component); components.remove(component); - super.removeComponent(component); } diff --git a/server/src/com/vaadin/ui/RichTextArea.java b/server/src/com/vaadin/ui/RichTextArea.java index 9d05181541..31327b3a6f 100644 --- a/server/src/com/vaadin/ui/RichTextArea.java +++ b/server/src/com/vaadin/ui/RichTextArea.java @@ -285,7 +285,7 @@ public class RichTextArea extends AbstractField<String> implements } @Override - protected boolean isEmpty() { + public boolean isEmpty() { return super.isEmpty() || getValue().length() == 0; } diff --git a/server/src/com/vaadin/ui/TabSheet.java b/server/src/com/vaadin/ui/TabSheet.java index e4060528ee..5528ea2ee9 100644 --- a/server/src/com/vaadin/ui/TabSheet.java +++ b/server/src/com/vaadin/ui/TabSheet.java @@ -202,7 +202,6 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, if (component != null && components.contains(component)) { int componentIndex = components.indexOf(component); - super.removeComponent(component); keyMapper.remove(component); components.remove(component); @@ -239,7 +238,6 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, fireSelectedTabChange(); } } - markAsDirty(); } } @@ -401,8 +399,9 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, setSelected(tabComponent); fireSelectedTabChange(); } + super.addComponent(tabComponent); - markAsDirty(); + return tab; } } @@ -974,16 +973,16 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, /** * Gets the icon alt text for the tab. - * + * * @since 7.2 */ public String getIconAlternateText(); /** * Sets the icon alt text for the tab. - * + * * @since 7.2 - * + * * @param iconAltText * the icon to set */ diff --git a/server/src/com/vaadin/ui/TextField.java b/server/src/com/vaadin/ui/TextField.java index 563810c76a..2a61e93211 100644 --- a/server/src/com/vaadin/ui/TextField.java +++ b/server/src/com/vaadin/ui/TextField.java @@ -48,7 +48,7 @@ public class TextField extends AbstractTextField { * Constructs an empty <code>TextField</code> with no caption. */ public TextField() { - setValue(""); + clear(); } /** @@ -107,7 +107,7 @@ public class TextField extends AbstractTextField { /* * (non-Javadoc) * - * @see com.vaadin.ui.AbstractField#readDesign(org.jsoup.nodes.Element , + * @see com.vaadin.ui.AbstractTextField#readDesign(org.jsoup.nodes.Element, * com.vaadin.ui.declarative.DesignContext) */ @Override @@ -135,4 +135,15 @@ public class TextField extends AbstractTextField { DesignAttributeHandler.writeAttribute("value", attr, getValue(), def.getValue(), String.class); } + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.AbstractField#clear() + */ + @Override + public void clear() { + setValue(""); + } + } diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java index 78cb5488e8..4bd4b67259 100644 --- a/server/src/com/vaadin/ui/UI.java +++ b/server/src/com/vaadin/ui/UI.java @@ -633,7 +633,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements this.embedId = embedId; // Actual theme - used for finding CustomLayout templates - getState().theme = request.getParameter("theme"); + setTheme(request.getParameter("theme")); getPage().init(request); @@ -1164,7 +1164,11 @@ public abstract class UI extends AbstractSingleComponentContainer implements * The new theme name */ public void setTheme(String theme) { - getState().theme = theme; + if(theme == null) { + getState().theme = null; + } else { + getState().theme = VaadinServlet.stripSpecialChars(theme); + } } /** diff --git a/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java b/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java index fcaabcc079..2f51b21f7c 100644 --- a/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java +++ b/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java @@ -249,71 +249,33 @@ public class ContainerEventProvider implements CalendarEditableEventProvider, @Override public List<CalendarEvent> getEvents(Date startDate, Date endDate) { eventCache.clear(); - - int[] rangeIndexes = getFirstAndLastEventIndex(startDate, endDate); - for (int i = rangeIndexes[0]; i <= rangeIndexes[1] - && i < container.size(); i++) { - eventCache.add(getEvent(i)); - } - return Collections.unmodifiableList(eventCache); - } - - /** - * Get the first event for a date - * - * @param date - * The date to search for, NUll returns first event in container - * @return Returns an array where the first item is the start index and the - * second item is the end item - */ - private int[] getFirstAndLastEventIndex(Date start, Date end) { - int startIndex = 0; int size = container.size(); assert size >= 0; - int endIndex = size - 1; - if (start != null) { - /* - * Iterating from the start of the container, if range is in the end - * of the container then this will be slow TODO This could be - * improved by using some sort of divide and conquer algorithm - */ - while (startIndex < size) { - Object id = container.getIdByIndex(startIndex); - Item item = container.getItem(id); - Date d = (Date) item.getItemProperty(startDateProperty) + for (int i = 0; i < size; i++) { + Object id = container.getIdByIndex(i); + Item item = container.getItem(id); + boolean add = true; + if (startDate != null) { + Date eventEnd = (Date) item.getItemProperty(endDateProperty) .getValue(); - if (d.compareTo(start) >= 0) { - break; + if (eventEnd.compareTo(startDate) < 0) { + add = false; } - startIndex++; } - } - - if (end != null) { - /* - * Iterate from the start index until range ends - */ - endIndex = startIndex; - while (endIndex < size - 1) { - Object id = container.getIdByIndex(endIndex); - Item item = container.getItem(id); - Date d = (Date) item.getItemProperty(endDateProperty) - .getValue(); - if (d == null) { - // No end date present, use start date - d = (Date) item.getItemProperty(startDateProperty) - .getValue(); + if (add && endDate != null) { + Date eventStart = (Date) item + .getItemProperty(startDateProperty).getValue(); + if (eventStart.compareTo(endDate) >= 0) { + break; // because container is sorted, all further events + // will be even later } - if (d.compareTo(end) >= 0) { - endIndex--; - break; - } - endIndex++; + } + if (add) { + eventCache.add(getEvent(i)); } } - - return new int[] { startIndex, endIndex }; + return Collections.unmodifiableList(eventCache); } /* diff --git a/server/tests/src/com/vaadin/data/util/BeanContainerTest.java b/server/tests/src/com/vaadin/data/util/BeanContainerTest.java index 4e0e98ec43..f22ab8478e 100644 --- a/server/tests/src/com/vaadin/data/util/BeanContainerTest.java +++ b/server/tests/src/com/vaadin/data/util/BeanContainerTest.java @@ -68,6 +68,19 @@ public class BeanContainerTest extends AbstractBeanContainerTest { return false; } + public void testGetType_existingProperty_typeReturned() { + BeanContainer<String, ClassName> container = getContainer(); + Assert.assertEquals( + "Unexpected type is returned for property 'simpleName'", + String.class, container.getType("simpleName")); + } + + public void testGetType_notExistingProperty_nullReturned() { + BeanContainer<String, ClassName> container = getContainer(); + Assert.assertNull("Not null type is returned for property ''", + container.getType("")); + } + public void testBasicOperations() { testBasicContainerOperations(getContainer()); } diff --git a/server/tests/src/com/vaadin/data/util/BeanItemContainerTest.java b/server/tests/src/com/vaadin/data/util/BeanItemContainerTest.java index b58d962d96..514bf70416 100644 --- a/server/tests/src/com/vaadin/data/util/BeanItemContainerTest.java +++ b/server/tests/src/com/vaadin/data/util/BeanItemContainerTest.java @@ -12,6 +12,7 @@ import org.junit.Assert; import com.vaadin.data.Container; import com.vaadin.data.Item; +import com.vaadin.data.util.NestedMethodPropertyTest.Address; /** * Test basic functionality of BeanItemContainer. @@ -71,6 +72,19 @@ public class BeanItemContainerTest extends AbstractBeanContainerTest { return false; } + public void testGetType_existingProperty_typeReturned() { + BeanItemContainer<ClassName> container = getContainer(); + Assert.assertEquals( + "Unexpected type is returned for property 'simpleName'", + String.class, container.getType("simpleName")); + } + + public void testGetType_notExistingProperty_nullReturned() { + BeanItemContainer<ClassName> container = getContainer(); + Assert.assertNull("Not null type is returned for property ''", + container.getType("")); + } + public void testBasicOperations() { testBasicContainerOperations(getContainer()); } @@ -727,4 +741,45 @@ public class BeanItemContainerTest extends AbstractBeanContainerTest { assertNull(container.getContainerProperty(john, "address.street") .getValue()); } + + public void testAddNestedContainerBeanBeforeData() { + BeanItemContainer<NestedMethodPropertyTest.Person> container = new BeanItemContainer<NestedMethodPropertyTest.Person>( + NestedMethodPropertyTest.Person.class); + + container.addNestedContainerBean("address"); + + assertTrue(container.getContainerPropertyIds().contains( + "address.street")); + + NestedMethodPropertyTest.Person john = new NestedMethodPropertyTest.Person( + "John", new Address("streetname", 12345)); + container.addBean(john); + + assertTrue(container.getItem(john).getItemPropertyIds() + .contains("address.street")); + assertEquals("streetname", + container.getItem(john).getItemProperty("address.street") + .getValue()); + + } + + public void testAddNestedContainerBeanAfterData() { + BeanItemContainer<NestedMethodPropertyTest.Person> container = new BeanItemContainer<NestedMethodPropertyTest.Person>( + NestedMethodPropertyTest.Person.class); + + NestedMethodPropertyTest.Person john = new NestedMethodPropertyTest.Person( + "John", new Address("streetname", 12345)); + container.addBean(john); + + container.addNestedContainerBean("address"); + + assertTrue(container.getContainerPropertyIds().contains( + "address.street")); + assertTrue(container.getItem(john).getItemPropertyIds() + .contains("address.street")); + assertEquals("streetname", + container.getItem(john).getItemProperty("address.street") + .getValue()); + + } } diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTableQueryTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTableQueryTest.java index d907f12321..f82ba49c3e 100644 --- a/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTableQueryTest.java +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTableQueryTest.java @@ -24,11 +24,15 @@ import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPool; import com.vaadin.data.util.sqlcontainer.query.OrderBy; import com.vaadin.data.util.sqlcontainer.query.TableQuery; +import static org.junit.Assert.assertTrue; + public class SQLContainerTableQueryTest { private static final int offset = SQLTestsConstants.offset; private static final String createGarbage = SQLTestsConstants.createGarbage; private JDBCConnectionPool connectionPool; + private TableQuery peopleQuery; + private SQLContainer peopleContainer; @Before public void setUp() throws SQLException { @@ -43,6 +47,10 @@ public class SQLContainerTableQueryTest { } DataGenerator.addPeopleToDatabase(connectionPool); + + peopleQuery = new TableQuery("people", connectionPool, + SQLTestsConstants.sqlGen); + peopleContainer = new SQLContainer(peopleQuery); } @After @@ -53,6 +61,24 @@ public class SQLContainerTableQueryTest { } @Test + public void itemWithExistingVersionColumnIsRemoved() + throws SQLException { + peopleContainer.setAutoCommit(true); + peopleQuery.setVersionColumn("ID"); + + assertTrue(peopleContainer.removeItem(peopleContainer.lastItemId())); + } + + @Test(expected = IllegalArgumentException.class) + public void itemWithNonExistingVersionColumnCannotBeRemoved() throws SQLException { + peopleQuery.setVersionColumn("version"); + + peopleContainer.removeItem(peopleContainer.lastItemId()); + + peopleContainer.commit(); + } + + @Test public void constructor_withTableQuery_shouldSucceed() throws SQLException { new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); @@ -63,8 +89,8 @@ public class SQLContainerTableQueryTest { throws SQLException { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); - Assert.assertTrue(container.containsId(new RowId( - new Object[] { 1 + offset }))); + assertTrue(container.containsId(new RowId( + new Object[]{1 + offset}))); } @Test @@ -410,11 +436,11 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); if (SQLTestsConstants.db == DB.ORACLE) { - Assert.assertTrue(container.isFirstId(new RowId( - new Object[] { new BigDecimal(0 + offset) }))); + assertTrue(container.isFirstId(new RowId( + new Object[]{new BigDecimal(0 + offset)}))); } else { - Assert.assertTrue(container.isFirstId(new RowId( - new Object[] { 0 + offset }))); + assertTrue(container.isFirstId(new RowId( + new Object[]{0 + offset}))); } } @@ -449,11 +475,11 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); if (SQLTestsConstants.db == DB.ORACLE) { - Assert.assertTrue(container.isLastId(new RowId( - new Object[] { new BigDecimal(3 + offset) }))); + assertTrue(container.isLastId(new RowId( + new Object[]{new BigDecimal(3 + offset)}))); } else { - Assert.assertTrue(container.isLastId(new RowId( - new Object[] { 3 + offset }))); + assertTrue(container.isLastId(new RowId( + new Object[]{3 + offset}))); } } @@ -463,11 +489,11 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); if (SQLTestsConstants.db == DB.ORACLE) { - Assert.assertTrue(container.isLastId(new RowId( - new Object[] { new BigDecimal(4999 + offset) }))); + assertTrue(container.isLastId(new RowId( + new Object[]{new BigDecimal(4999 + offset)}))); } else { - Assert.assertTrue(container.isLastId(new RowId( - new Object[] { 4999 + offset }))); + assertTrue(container.isLastId(new RowId( + new Object[]{4999 + offset}))); } } @@ -478,7 +504,7 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); for (int i = 0; i < 5000; i++) { - Assert.assertTrue(container.containsId(container.getIdByIndex(i))); + assertTrue(container.containsId(container.getIdByIndex(i))); } } @@ -490,7 +516,7 @@ public class SQLContainerTableQueryTest { connectionPool, SQLTestsConstants.sqlGen)); container.setAutoCommit(true); for (int i = 0; i < 5000; i++) { - Assert.assertTrue(container.containsId(container.getIdByIndex(i))); + assertTrue(container.containsId(container.getIdByIndex(i))); } } @@ -523,7 +549,7 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); container.setAutoCommit(true); - Assert.assertTrue(container.isAutoCommit()); + assertTrue(container.isAutoCommit()); container.setAutoCommit(false); Assert.assertFalse(container.isAutoCommit()); } @@ -613,7 +639,7 @@ public class SQLContainerTableQueryTest { container.setAutoCommit(true); Object itemId = container.addItem(); Assert.assertNotNull(itemId); - Assert.assertTrue(itemId instanceof RowId); + assertTrue(itemId instanceof RowId); Assert.assertFalse(itemId instanceof TemporaryRowId); } @@ -696,7 +722,7 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); Object id = container.addItem(); - Assert.assertTrue(container.getItemIds().contains(id)); + assertTrue(container.getItemIds().contains(id)); } @Test @@ -717,7 +743,7 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); Object id = container.addItem(); - Assert.assertTrue(container.containsId(id)); + assertTrue(container.containsId(id)); } @Test @@ -747,7 +773,7 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("garbage", connectionPool, SQLTestsConstants.sqlGen)); Object id = container.addItem(); - Assert.assertTrue(container.isFirstId(id)); + assertTrue(container.isFirstId(id)); } @Test @@ -756,7 +782,7 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); Object id = container.addItem(); - Assert.assertTrue(container.isLastId(id)); + assertTrue(container.isLastId(id)); } @Test @@ -766,7 +792,7 @@ public class SQLContainerTableQueryTest { connectionPool, SQLTestsConstants.sqlGen)); container.addItem(); Object id2 = container.addItem(); - Assert.assertTrue(container.isLastId(id2)); + assertTrue(container.isLastId(id2)); } @Test @@ -785,7 +811,7 @@ public class SQLContainerTableQueryTest { connectionPool, SQLTestsConstants.sqlGen)); int size = container.size(); Object id = container.firstItemId(); - Assert.assertTrue(container.removeItem(id)); + assertTrue(container.removeItem(id)); Assert.assertNotSame(id, container.firstItemId()); Assert.assertEquals(size - 1, container.size()); } @@ -795,7 +821,7 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); Object id = container.firstItemId(); - Assert.assertTrue(container.removeItem(id)); + assertTrue(container.removeItem(id)); Assert.assertFalse(container.containsId(id)); } @@ -806,7 +832,7 @@ public class SQLContainerTableQueryTest { connectionPool, SQLTestsConstants.sqlGen)); Object id = container.addItem(); int size = container.size(); - Assert.assertTrue(container.removeItem(id)); + assertTrue(container.removeItem(id)); Assert.assertFalse(container.containsId(id)); Assert.assertEquals(size - 1, container.size()); } @@ -816,7 +842,7 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); Object id = container.firstItemId(); - Assert.assertTrue(container.removeItem(id)); + assertTrue(container.removeItem(id)); Assert.assertNull(container.getItem(id)); } @@ -826,7 +852,7 @@ public class SQLContainerTableQueryTest { connectionPool, SQLTestsConstants.sqlGen)); Object id = container.addItem(); Assert.assertNotNull(container.getItem(id)); - Assert.assertTrue(container.removeItem(id)); + assertTrue(container.removeItem(id)); Assert.assertNull(container.getItem(id)); } @@ -836,8 +862,8 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); Object id = container.firstItemId(); - Assert.assertTrue(container.getItemIds().contains(id)); - Assert.assertTrue(container.removeItem(id)); + assertTrue(container.getItemIds().contains(id)); + assertTrue(container.removeItem(id)); Assert.assertFalse(container.getItemIds().contains(id)); } @@ -847,8 +873,8 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); Object id = container.addItem(); - Assert.assertTrue(container.getItemIds().contains(id)); - Assert.assertTrue(container.removeItem(id)); + assertTrue(container.getItemIds().contains(id)); + assertTrue(container.removeItem(id)); Assert.assertFalse(container.getItemIds().contains(id)); } @@ -857,8 +883,8 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); Object id = container.firstItemId(); - Assert.assertTrue(container.containsId(id)); - Assert.assertTrue(container.removeItem(id)); + assertTrue(container.containsId(id)); + assertTrue(container.removeItem(id)); Assert.assertFalse(container.containsId(id)); } @@ -869,8 +895,8 @@ public class SQLContainerTableQueryTest { SQLTestsConstants.sqlGen); SQLContainer container = new SQLContainer(query); Object id = container.addItem(); - Assert.assertTrue(container.containsId(id)); - Assert.assertTrue(container.removeItem(id)); + assertTrue(container.containsId(id)); + assertTrue(container.removeItem(id)); Assert.assertFalse(container.containsId(id)); } @@ -882,7 +908,7 @@ public class SQLContainerTableQueryTest { Object first = container.getIdByIndex(0); Object second = container.getIdByIndex(1); Object third = container.getIdByIndex(2); - Assert.assertTrue(container.removeItem(second)); + assertTrue(container.removeItem(second)); Assert.assertEquals(third, container.nextItemId(first)); } @@ -894,7 +920,7 @@ public class SQLContainerTableQueryTest { Object first = container.lastItemId(); Object second = container.addItem(); Object third = container.addItem(); - Assert.assertTrue(container.removeItem(second)); + assertTrue(container.removeItem(second)); Assert.assertEquals(third, container.nextItemId(first)); } @@ -906,7 +932,7 @@ public class SQLContainerTableQueryTest { Object first = container.getIdByIndex(0); Object second = container.getIdByIndex(1); Object third = container.getIdByIndex(2); - Assert.assertTrue(container.removeItem(second)); + assertTrue(container.removeItem(second)); Assert.assertEquals(first, container.prevItemId(third)); } @@ -918,7 +944,7 @@ public class SQLContainerTableQueryTest { Object first = container.lastItemId(); Object second = container.addItem(); Object third = container.addItem(); - Assert.assertTrue(container.removeItem(second)); + assertTrue(container.removeItem(second)); Assert.assertEquals(first, container.prevItemId(third)); } @@ -928,7 +954,7 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); Object first = container.firstItemId(); - Assert.assertTrue(container.removeItem(first)); + assertTrue(container.removeItem(first)); Assert.assertNotSame(first, container.firstItemId()); } @@ -941,7 +967,7 @@ public class SQLContainerTableQueryTest { Object first = container.addItem(); Object second = container.addItem(); Assert.assertSame(first, container.firstItemId()); - Assert.assertTrue(container.removeItem(first)); + assertTrue(container.removeItem(first)); Assert.assertSame(second, container.firstItemId()); } @@ -951,7 +977,7 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); Object last = container.lastItemId(); - Assert.assertTrue(container.removeItem(last)); + assertTrue(container.removeItem(last)); Assert.assertNotSame(last, container.lastItemId()); } @@ -962,7 +988,7 @@ public class SQLContainerTableQueryTest { connectionPool, SQLTestsConstants.sqlGen)); Object last = container.addItem(); Assert.assertSame(last, container.lastItemId()); - Assert.assertTrue(container.removeItem(last)); + assertTrue(container.removeItem(last)); Assert.assertNotSame(last, container.lastItemId()); } @@ -972,7 +998,7 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); Object first = container.firstItemId(); - Assert.assertTrue(container.removeItem(first)); + assertTrue(container.removeItem(first)); Assert.assertFalse(container.isFirstId(first)); } @@ -985,7 +1011,7 @@ public class SQLContainerTableQueryTest { Object first = container.addItem(); container.addItem(); Assert.assertSame(first, container.firstItemId()); - Assert.assertTrue(container.removeItem(first)); + assertTrue(container.removeItem(first)); Assert.assertFalse(container.isFirstId(first)); } @@ -995,7 +1021,7 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); Object last = container.lastItemId(); - Assert.assertTrue(container.removeItem(last)); + assertTrue(container.removeItem(last)); Assert.assertFalse(container.isLastId(last)); } @@ -1006,7 +1032,7 @@ public class SQLContainerTableQueryTest { connectionPool, SQLTestsConstants.sqlGen)); Object last = container.addItem(); Assert.assertSame(last, container.lastItemId()); - Assert.assertTrue(container.removeItem(last)); + assertTrue(container.removeItem(last)); Assert.assertFalse(container.isLastId(last)); } @@ -1015,7 +1041,7 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); Object id = container.getIdByIndex(2); - Assert.assertTrue(container.removeItem(id)); + assertTrue(container.removeItem(id)); Assert.assertEquals(-1, container.indexOfId(id)); } @@ -1025,8 +1051,8 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); Object id = container.addItem(); - Assert.assertTrue(container.indexOfId(id) != -1); - Assert.assertTrue(container.removeItem(id)); + assertTrue(container.indexOfId(id) != -1); + assertTrue(container.removeItem(id)); Assert.assertEquals(-1, container.indexOfId(id)); } @@ -1036,7 +1062,7 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); Object id = container.getIdByIndex(2); - Assert.assertTrue(container.removeItem(id)); + assertTrue(container.removeItem(id)); Assert.assertNotSame(id, container.getIdByIndex(2)); } @@ -1048,7 +1074,7 @@ public class SQLContainerTableQueryTest { Object id = container.addItem(); container.addItem(); int index = container.indexOfId(id); - Assert.assertTrue(container.removeItem(id)); + assertTrue(container.removeItem(id)); Assert.assertNotSame(id, container.getIdByIndex(index)); } @@ -1056,7 +1082,7 @@ public class SQLContainerTableQueryTest { public void removeAllItems_table_shouldSucceed() throws SQLException { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); - Assert.assertTrue(container.removeAllItems()); + assertTrue(container.removeAllItems()); Assert.assertEquals(0, container.size()); } @@ -1067,10 +1093,30 @@ public class SQLContainerTableQueryTest { connectionPool, SQLTestsConstants.sqlGen)); container.addItem(); container.addItem(); - Assert.assertTrue(container.removeAllItems()); + assertTrue(container.removeAllItems()); Assert.assertEquals(0, container.size()); } + // Set timeout to ensure there is no infinite looping (#12882) + @Test(timeout = 1000) + public void removeAllItems_manyItems_commit_shouldSucceed() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, SQLTestsConstants.sqlGen)); + final int itemNumber = (SQLContainer.CACHE_RATIO + 1) + * SQLContainer.DEFAULT_PAGE_LENGTH + 1; + container.removeAllItems(); + Assert.assertEquals(container.size(), 0); + for (int i = 0; i < itemNumber; ++i) { + container.addItem(); + } + container.commit(); + Assert.assertEquals(container.size(), itemNumber); + assertTrue(container.removeAllItems()); + container.commit(); + Assert.assertEquals(container.size(), 0); + } + @Test public void commit_tableAddedItem_shouldBeWrittenToDB() throws SQLException { TableQuery query = new TableQuery("people", connectionPool, @@ -1078,7 +1124,7 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(query); Object id = container.addItem(); container.getContainerProperty(id, "NAME").setValue("New Name"); - Assert.assertTrue(id instanceof TemporaryRowId); + assertTrue(id instanceof TemporaryRowId); Assert.assertSame(id, container.lastItemId()); container.commit(); Assert.assertFalse(container.lastItemId() instanceof TemporaryRowId); @@ -1097,7 +1143,7 @@ public class SQLContainerTableQueryTest { Object id2 = container.addItem(); container.getContainerProperty(id, "NAME").setValue("Herbert"); container.getContainerProperty(id2, "NAME").setValue("Larry"); - Assert.assertTrue(id2 instanceof TemporaryRowId); + assertTrue(id2 instanceof TemporaryRowId); Assert.assertSame(id2, container.lastItemId()); container.commit(); Object nextToLast = container.getIdByIndex(container.size() - 2); @@ -1137,6 +1183,20 @@ public class SQLContainerTableQueryTest { } @Test + public void commit_removeModifiedItem_shouldSucceed() throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + SQLTestsConstants.sqlGen); + SQLContainer container = new SQLContainer(query); + int size = container.size(); + Object key = container.firstItemId(); + Item row = container.getItem(key); + row.getItemProperty("NAME").setValue("Pekka"); + assertTrue(container.removeItem(key)); + container.commit(); + Assert.assertEquals(size - 1, container.size()); + } + + @Test public void rollback_tableItemAdded_discardsAddedItem() throws SQLException { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); @@ -1183,7 +1243,7 @@ public class SQLContainerTableQueryTest { Assert.assertFalse(container.isModified()); RowItem last = (RowItem) container.getItem(container.lastItemId()); container.itemChangeNotification(last); - Assert.assertTrue(container.isModified()); + assertTrue(container.isModified()); } @Test @@ -1239,7 +1299,7 @@ public class SQLContainerTableQueryTest { connectionPool, SQLTestsConstants.sqlGen)); Assert.assertFalse(container.isModified()); container.removeItem(container.lastItemId()); - Assert.assertTrue(container.isModified()); + assertTrue(container.isModified()); } @Test @@ -1248,7 +1308,7 @@ public class SQLContainerTableQueryTest { connectionPool, SQLTestsConstants.sqlGen)); Assert.assertFalse(container.isModified()); container.addItem(); - Assert.assertTrue(container.isModified()); + assertTrue(container.isModified()); } @Test @@ -1258,7 +1318,7 @@ public class SQLContainerTableQueryTest { Assert.assertFalse(container.isModified()); container.getContainerProperty(container.lastItemId(), "NAME") .setValue("foo"); - Assert.assertTrue(container.isModified()); + assertTrue(container.isModified()); } @Test @@ -1267,9 +1327,9 @@ public class SQLContainerTableQueryTest { SQLContainer container = new SQLContainer(new TableQuery("people", connectionPool, SQLTestsConstants.sqlGen)); Collection<?> sortableIds = container.getSortableContainerPropertyIds(); - Assert.assertTrue(sortableIds.contains("ID")); - Assert.assertTrue(sortableIds.contains("NAME")); - Assert.assertTrue(sortableIds.contains("AGE")); + assertTrue(sortableIds.contains("ID")); + assertTrue(sortableIds.contains("NAME")); + assertTrue(sortableIds.contains("AGE")); Assert.assertEquals(3, sortableIds.size()); if (SQLTestsConstants.db == DB.MSSQL || SQLTestsConstants.db == DB.ORACLE) { diff --git a/server/tests/src/com/vaadin/tests/data/converter/TestDefaultConverterFactory.java b/server/tests/src/com/vaadin/tests/data/converter/TestDefaultConverterFactory.java new file mode 100644 index 0000000000..e1becf43e1 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/converter/TestDefaultConverterFactory.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.data.converter; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Date; +import java.util.Locale; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.util.converter.DefaultConverterFactory; + +public class TestDefaultConverterFactory { + + private DefaultConverterFactory factory = new DefaultConverterFactory(); + + @Test + public void stringToBigDecimal() { + assertConverter("14", new BigDecimal("14")); + } + + @Test + public void stringToBigInteger() { + assertConverter("14", new BigInteger("14")); + } + + @Test + public void stringToDouble() { + assertConverter("14", new Double("14")); + } + + @Test + public void stringToFloat() { + assertConverter("14", new Float("14")); + } + + @Test + public void stringToInteger() { + assertConverter("14", new Integer("14")); + } + + @Test + public void stringToLong() { + assertConverter("14", new Long("14")); + } + + @SuppressWarnings("deprecation") + @Test + public void stringToDate() { + assertConverter("Oct 12, 2014 12:00:00 AM", new Date(2014 - 1900, + 10 - 1, 12)); + } + + @Test + public void sqlDateToDate() { + long l = 1413071210000L; + assertConverter(new java.sql.Date(l), new java.util.Date(l)); + } + + @SuppressWarnings("deprecation") + @Test + public void longToDate() { + assertConverter(1413061200000L, new Date(2014 - 1900, 10 - 1, 12)); + } + + public enum Foo { + BAR, BAZ; + } + + @Test + public void stringToEnum() { + assertConverter("Bar", Foo.BAR); + } + + @Test + public void stringToShort() { + assertConverter("14", new Short("14")); + } + + @Test + public void stringToByte() { + assertConverter("14", new Byte("14")); + } + + private <T, U> void assertConverter(T t, U u) { + Class<T> tClass = (Class<T>) t.getClass(); + Class<U> uClass = (Class<U>) u.getClass(); + + U tConvertedToU = factory.createConverter(tClass, uClass) + .convertToModel(t, uClass, Locale.ENGLISH); + Assert.assertEquals( + "Incorrect type of value converted from " + + tClass.getSimpleName() + " to " + + uClass.getSimpleName(), uClass, + tConvertedToU.getClass()); + Assert.assertEquals( + "Incorrect conversion of " + t + " to " + + uClass.getSimpleName(), u, tConvertedToU); + + T uConvertedToT = factory.createConverter(uClass, tClass) + .convertToModel(u, tClass, Locale.ENGLISH); + Assert.assertEquals( + "Incorrect type of value converted from " + + uClass.getSimpleName() + " to " + + tClass.getSimpleName(), tClass, + uConvertedToT.getClass()); + Assert.assertEquals( + "Incorrect conversion of " + u + " to " + + tClass.getSimpleName(), t, uConvertedToT); + + } + +} diff --git a/server/tests/src/com/vaadin/tests/data/converter/TestStringToBigIntegerConverter.java b/server/tests/src/com/vaadin/tests/data/converter/TestStringToBigIntegerConverter.java index 641f18c865..8d493609fe 100644 --- a/server/tests/src/com/vaadin/tests/data/converter/TestStringToBigIntegerConverter.java +++ b/server/tests/src/com/vaadin/tests/data/converter/TestStringToBigIntegerConverter.java @@ -15,39 +15,43 @@ */ package com.vaadin.tests.data.converter; -import java.math.BigDecimal; +import java.math.BigInteger; import java.util.Locale; import junit.framework.TestCase; -import com.vaadin.data.util.converter.StringToBigDecimalConverter; +import com.vaadin.data.util.converter.StringToBigIntegerConverter; public class TestStringToBigIntegerConverter extends TestCase { - StringToBigDecimalConverter converter = new StringToBigDecimalConverter(); + StringToBigIntegerConverter converter = new StringToBigIntegerConverter(); public void testNullConversion() { - assertEquals(null, - converter.convertToModel(null, BigDecimal.class, null)); + assertEquals("Null value was converted incorrectly", null, + converter.convertToModel(null, BigInteger.class, null)); } public void testEmptyStringConversion() { - assertEquals(null, converter.convertToModel("", BigDecimal.class, null)); + assertEquals("Empty value was converted incorrectly", null, + converter.convertToModel("", BigInteger.class, null)); } public void testValueParsing() { - BigDecimal converted = converter.convertToModel("10", BigDecimal.class, - null); - BigDecimal expected = new BigDecimal(10); - assertEquals(expected, converted); + String bigInt = "1180591620717411303424"; // 2^70 > 2^63 - 1 + BigInteger converted = converter.convertToModel(bigInt, + BigInteger.class, null); + BigInteger expected = new BigInteger(bigInt); + assertEquals("Value bigger than max long was converted incorrectly", + expected, converted); } public void testValueFormatting() { - BigDecimal bd = new BigDecimal(1000); + BigInteger bd = new BigInteger("1000"); String expected = "1.000"; String converted = converter.convertToPresentation(bd, String.class, Locale.GERMAN); - assertEquals(expected, converted); + assertEquals("Value with specific locale was converted incorrectly", + expected, converted); } } diff --git a/server/tests/src/com/vaadin/tests/data/converter/TestStringToByteConverter.java b/server/tests/src/com/vaadin/tests/data/converter/TestStringToByteConverter.java index 440d056c06..19a68fbfdb 100644 --- a/server/tests/src/com/vaadin/tests/data/converter/TestStringToByteConverter.java +++ b/server/tests/src/com/vaadin/tests/data/converter/TestStringToByteConverter.java @@ -16,25 +16,28 @@ public class TestStringToByteConverter extends TestCase { converter); public void testNullConversion() { - assertEquals(null, converter.convertToModel(null, Byte.class, null)); + assertEquals("Null value was converted incorrectly", null, + converter.convertToModel(null, Byte.class, null)); } public void testReverseNullConversion() { - assertEquals(null, + assertEquals("Null value reversely was converted incorrectly", null, reverseConverter.convertToModel(null, String.class, null)); } public void testEmptyStringConversion() { - assertEquals(null, converter.convertToModel("", Byte.class, null)); + assertEquals("Empty value was converted incorrectly", null, + converter.convertToModel("", Byte.class, null)); } public void testValueConversion() { - assertEquals(Byte.valueOf((byte) 10), + assertEquals("Byte value was converted incorrectly", + Byte.valueOf((byte) 10), converter.convertToModel("10", Byte.class, null)); } public void testReverseValueConversion() { - assertEquals( + assertEquals("Byte value reversely was converted incorrectly", reverseConverter.convertToModel((byte) 10, String.class, null), "10"); } @@ -43,7 +46,8 @@ public class TestStringToByteConverter extends TestCase { byte b = converter.convertToModel("127", Byte.class, null); Assert.assertEquals(Byte.MAX_VALUE, b); b = converter.convertToModel("-128", Byte.class, null); - assertEquals(Byte.MIN_VALUE, b); + assertEquals("Min byte value was converted incorrectly", + Byte.MIN_VALUE, b); } public void testValueOutOfRange() { diff --git a/server/tests/src/com/vaadin/tests/data/converter/TestStringToEnumConverter.java b/server/tests/src/com/vaadin/tests/data/converter/TestStringToEnumConverter.java index 2b19395c08..5dc24ca43a 100644 --- a/server/tests/src/com/vaadin/tests/data/converter/TestStringToEnumConverter.java +++ b/server/tests/src/com/vaadin/tests/data/converter/TestStringToEnumConverter.java @@ -3,6 +3,7 @@ package com.vaadin.tests.data.converter; import junit.framework.TestCase; import com.vaadin.data.util.converter.Converter; +import com.vaadin.data.util.converter.Converter.ConversionException; import com.vaadin.data.util.converter.ReverseConverter; import com.vaadin.data.util.converter.StringToEnumConverter; @@ -16,6 +17,19 @@ public class TestStringToEnumConverter extends TestCase { Converter<Enum, String> reverseConverter = new ReverseConverter<Enum, String>( converter); + public void testEmptyStringConversion() { + assertEquals(null, converter.convertToModel("", Enum.class, null)); + } + + public void testInvalidEnumClassConversion() { + try { + converter.convertToModel("Foo", Enum.class, null); + fail("No exception thrown"); + } catch (ConversionException e) { + // OK + } + } + public void testNullConversion() { assertEquals(null, converter.convertToModel(null, Enum.class, null)); } diff --git a/server/tests/src/com/vaadin/tests/data/converter/TestStringToShortConverter.java b/server/tests/src/com/vaadin/tests/data/converter/TestStringToShortConverter.java index 35547d2570..542c580025 100644 --- a/server/tests/src/com/vaadin/tests/data/converter/TestStringToShortConverter.java +++ b/server/tests/src/com/vaadin/tests/data/converter/TestStringToShortConverter.java @@ -16,25 +16,29 @@ public class TestStringToShortConverter extends TestCase { converter); public void testNullConversion() { - assertEquals(null, converter.convertToModel(null, Short.class, null)); + assertEquals("Null value was converted incorrectly", null, + converter.convertToModel(null, Short.class, null)); } public void testReverseNullConversion() { - assertEquals(null, + assertEquals("Null value reversely was converted incorrectly", null, reverseConverter.convertToModel(null, String.class, null)); } public void testEmptyStringConversion() { - assertEquals(null, converter.convertToModel("", Short.class, null)); + assertEquals("Empty value was converted incorrectly", null, + converter.convertToModel("", Short.class, null)); } public void testValueConversion() { - assertEquals(Short.valueOf((short) 10), + assertEquals("Short value was converted incorrectly", + Short.valueOf((short) 10), converter.convertToModel("10", Short.class, null)); } public void testReverseValueConversion() { assertEquals( + "Short value reversely was converted incorrectly", reverseConverter.convertToModel((short) 10, String.class, null), "10"); } @@ -43,7 +47,8 @@ public class TestStringToShortConverter extends TestCase { short b = converter.convertToModel("32767", Short.class, null); Assert.assertEquals(Short.MAX_VALUE, b); b = converter.convertToModel("-32768", Short.class, null); - assertEquals(Short.MIN_VALUE, b); + assertEquals("Min short value was converted incorrectly", + Short.MIN_VALUE, b); } public void testValueOutOfRange() { diff --git a/server/tests/src/com/vaadin/tests/server/FileResourceTest.java b/server/tests/src/com/vaadin/tests/server/FileResourceTest.java new file mode 100644 index 0000000000..4798fb9f05 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/FileResourceTest.java @@ -0,0 +1,36 @@ +/* + * 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.server; + +import java.io.File; + +import org.junit.Test; + +import com.vaadin.server.FileResource; + +public class FileResourceTest { + + @Test(expected = IllegalArgumentException.class) + public void nullFile() { + new FileResource(null); + } + + @Test(expected = RuntimeException.class) + public void nonExistingFile() { + new FileResource(new File("nonexisting")).getStream(); + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/component/fieldgroup/BeanFieldGroupTest.java b/server/tests/src/com/vaadin/tests/server/component/fieldgroup/BeanFieldGroupTest.java index 112d36d884..9c37b91ef5 100644 --- a/server/tests/src/com/vaadin/tests/server/component/fieldgroup/BeanFieldGroupTest.java +++ b/server/tests/src/com/vaadin/tests/server/component/fieldgroup/BeanFieldGroupTest.java @@ -5,9 +5,11 @@ import static org.junit.Assert.assertEquals; import org.junit.Assert; import org.junit.Test; +import com.vaadin.data.Item; import com.vaadin.data.fieldgroup.BeanFieldGroup; import com.vaadin.data.fieldgroup.FieldGroup.CommitException; import com.vaadin.data.fieldgroup.PropertyId; +import com.vaadin.data.util.BeanItem; import com.vaadin.ui.Field; import com.vaadin.ui.TextField; @@ -133,4 +135,23 @@ public class BeanFieldGroupTest { assertEquals(bean.nestedBean.hello, helloField.getValue().toString()); } + @Test + public void setDataSource_nullBean_nullBeanIsSetInDataSource() { + BeanFieldGroup<MyBean> group = new BeanFieldGroup<MyBean>(MyBean.class); + + group.setItemDataSource((MyBean) null); + + BeanItem<MyBean> dataSource = group.getItemDataSource(); + Assert.assertNull("Data source is null for null bean", dataSource); + } + + @Test + public void setDataSource_nullItem_nullDataSourceIsSet() { + BeanFieldGroup<MyBean> group = new BeanFieldGroup<MyBean>(MyBean.class); + + group.setItemDataSource((Item) null); + BeanItem<MyBean> dataSource = group.getItemDataSource(); + Assert.assertNull("Group returns not null data source", dataSource); + } + } diff --git a/server/tests/src/com/vaadin/tests/server/components/ComponentAttachDetachListenerTest.java b/server/tests/src/com/vaadin/tests/server/components/ComponentAttachDetachListenerTest.java index df515795eb..d8b366ffbc 100644 --- a/server/tests/src/com/vaadin/tests/server/components/ComponentAttachDetachListenerTest.java +++ b/server/tests/src/com/vaadin/tests/server/components/ComponentAttachDetachListenerTest.java @@ -9,6 +9,7 @@ import com.vaadin.ui.AbsoluteLayout.ComponentPosition; import com.vaadin.ui.AbstractOrderedLayout; import com.vaadin.ui.Component; import com.vaadin.ui.CssLayout; +import com.vaadin.ui.CustomLayout; import com.vaadin.ui.GridLayout; import com.vaadin.ui.GridLayout.Area; import com.vaadin.ui.HasComponents; @@ -25,6 +26,7 @@ public class ComponentAttachDetachListenerTest extends TestCase { private GridLayout gridlayout; private AbsoluteLayout absolutelayout; private CssLayout csslayout; + private CustomLayout customlayout; // General variables private int attachCounter = 0; @@ -143,6 +145,10 @@ public class ComponentAttachDetachListenerTest extends TestCase { csslayout = new CssLayout(); csslayout.addComponentAttachListener(new MyAttachListener()); csslayout.addComponentDetachListener(new MyDetachListener()); + + customlayout = new CustomLayout("<div location='loc'/>"); + customlayout.addComponentAttachListener(new MyAttachListener()); + customlayout.addComponentDetachListener(new MyDetachListener()); } public void testOrderedLayoutAttachListener() { @@ -342,4 +348,48 @@ public class ComponentAttachDetachListenerTest extends TestCase { // The detached component should not be found in the container assertFalse(foundInContainer); } + + public void testCustomLayoutAttachListener() { + // Reset state variables + resetVariables(); + + // Add component -> Should trigger attach listener + Component comp = new Label(); + customlayout.addComponent(comp, "loc"); + + assertEquals("Attach counter should get incremented", 1, attachCounter); + + assertSame("The attached component should be the label", comp, + attachedComponent); + + assertSame("The attached target should be the layout", customlayout, + attachTarget); + + assertTrue("The attached component should be found in the container", + foundInContainer); + } + + public void testCustomLayoutDetachListener() { + // Add a component to detach + Component comp = new Label(); + customlayout.addComponent(comp); + + // Reset state variables (since they are set by the attach listener) + resetVariables(); + + // Detach the component -> triggers the detach listener + customlayout.removeComponent(comp); + + assertEquals("Detach counter should get incremented", 1, detachCounter); + + assertSame("The detached component should be the label", comp, + detachedComponent); + + assertSame("The detached target should be the layout", customlayout, + detachedTarget); + + assertFalse( + "The detached component should not be found in the container", + foundInContainer); + } } diff --git a/server/tests/src/com/vaadin/ui/AbstractSelectTest.java b/server/tests/src/com/vaadin/ui/AbstractSelectTest.java index 83d66ee9d5..bd399f088c 100644 --- a/server/tests/src/com/vaadin/ui/AbstractSelectTest.java +++ b/server/tests/src/com/vaadin/ui/AbstractSelectTest.java @@ -16,10 +16,13 @@ package com.vaadin.ui; import java.util.ArrayList; +import java.util.HashSet; import org.junit.Assert; import org.junit.Test; +import com.vaadin.data.util.ObjectProperty; + public class AbstractSelectTest { @Test @@ -73,4 +76,72 @@ public class AbstractSelectTest { .toArray()); } + + @Test + public void singleSelectInitiallyEmpty() { + AbstractSelect s = new ListSelect(); + Assert.assertTrue(s.isEmpty()); + } + + @Test + public void singleSelectEmptyAfterClearUsingPDS() { + AbstractSelect s = new ListSelect(); + s.addItem("foo"); + s.addItem("bar"); + s.setPropertyDataSource(new ObjectProperty<String>("foo")); + + Assert.assertFalse(s.isEmpty()); + s.clear(); + Assert.assertTrue(s.isEmpty()); + } + + @Test + public void singleSelectEmptyAfterClear() { + AbstractSelect s = new ListSelect(); + s.addItem("foo"); + s.addItem("bar"); + s.setValue("bar"); + + Assert.assertFalse(s.isEmpty()); + s.clear(); + Assert.assertTrue(s.isEmpty()); + } + + @Test + public void multiSelectInitiallyEmpty() { + AbstractSelect s = new ListSelect(); + s.setMultiSelect(true); + Assert.assertTrue(s.isEmpty()); + } + + @Test + public void multiSelectEmptyAfterClearUsingPDS() { + AbstractSelect s = new ListSelect(); + s.setMultiSelect(true); + s.addItem("foo"); + s.addItem("bar"); + HashSet<String> sel = new HashSet<String>(); + sel.add("foo"); + sel.add("bar"); + s.setPropertyDataSource(new ObjectProperty<HashSet>(sel)); + + Assert.assertFalse(s.isEmpty()); + s.clear(); + Assert.assertTrue(s.isEmpty()); + } + + @Test + public void multiSelectEmptyAfterClear() { + AbstractSelect s = new ListSelect(); + s.setMultiSelect(true); + s.addItem("foo"); + s.addItem("bar"); + s.select("foo"); + s.select("bar"); + + Assert.assertFalse(s.isEmpty()); + s.clear(); + Assert.assertTrue(s.isEmpty()); + } + } diff --git a/server/tests/src/com/vaadin/ui/RichTextAreaTest.java b/server/tests/src/com/vaadin/ui/RichTextAreaTest.java new file mode 100644 index 0000000000..ce0dfdc696 --- /dev/null +++ b/server/tests/src/com/vaadin/ui/RichTextAreaTest.java @@ -0,0 +1,47 @@ +/* + * 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.ui; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.util.ObjectProperty; + +public class RichTextAreaTest { + @Test + public void initiallyEmpty() { + RichTextArea tf = new RichTextArea(); + Assert.assertTrue(tf.isEmpty()); + } + + @Test + public void emptyAfterClearUsingPDS() { + RichTextArea tf = new RichTextArea(new ObjectProperty<String>("foo")); + Assert.assertFalse(tf.isEmpty()); + tf.clear(); + Assert.assertTrue(tf.isEmpty()); + } + + @Test + public void emptyAfterClear() { + RichTextArea tf = new RichTextArea(); + tf.setValue("foobar"); + Assert.assertFalse(tf.isEmpty()); + tf.clear(); + Assert.assertTrue(tf.isEmpty()); + } + +} diff --git a/server/tests/src/com/vaadin/ui/TextAreaTest.java b/server/tests/src/com/vaadin/ui/TextAreaTest.java new file mode 100644 index 0000000000..e7e99c19e9 --- /dev/null +++ b/server/tests/src/com/vaadin/ui/TextAreaTest.java @@ -0,0 +1,47 @@ +/* + * 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.ui; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.util.ObjectProperty; + +public class TextAreaTest { + @Test + public void initiallyEmpty() { + TextArea tf = new TextArea(); + Assert.assertTrue(tf.isEmpty()); + } + + @Test + public void emptyAfterClearUsingPDS() { + TextArea tf = new TextArea(new ObjectProperty<String>("foo")); + Assert.assertFalse(tf.isEmpty()); + tf.clear(); + Assert.assertTrue(tf.isEmpty()); + } + + @Test + public void emptyAfterClear() { + TextArea tf = new TextArea(); + tf.setValue("foobar"); + Assert.assertFalse(tf.isEmpty()); + tf.clear(); + Assert.assertTrue(tf.isEmpty()); + } + +} diff --git a/server/tests/src/com/vaadin/ui/UIThemeEscaping.java b/server/tests/src/com/vaadin/ui/UIThemeEscaping.java new file mode 100644 index 0000000000..236f283823 --- /dev/null +++ b/server/tests/src/com/vaadin/ui/UIThemeEscaping.java @@ -0,0 +1,89 @@ +/* + * 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.ui; + +import com.vaadin.server.VaadinRequest; +import org.junit.Before; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class UIThemeEscaping { + + private UI ui; + + private void initUiWithTheme(String theme) { + VaadinRequest request = getRequestWithTheme(theme); + + ui.doInit(request, 1234, "foobar"); + } + + private VaadinRequest getRequestWithTheme(String theme) { + VaadinRequest request = mock(VaadinRequest.class); + + when(request.getParameter("theme")).thenReturn(theme); + + return request; + } + + @Before + public void setup() { + ui = new UI() { + @Override + protected void init(VaadinRequest request) { + // Nothing to do + } + }; + } + + @Test + public void dangerousCharactersAreRemoved() { + ui.setTheme("a<å(_\"$"); + + assertThat(ui.getTheme(), is("aå_$")); + } + + @Test + public void nullThemeIsSet() { + ui.setTheme("foobar"); + + ui.setTheme(null); + + assertThat(ui.getTheme(), is(nullValue())); + } + + @Test + public void themeIsSetOnInit() { + ui.setTheme("foobar"); + + initUiWithTheme("bar"); + + assertThat(ui.getTheme(), is("bar")); + } + + @Test + public void nullThemeIsSetOnInit() { + ui.setTheme("foobar"); + + initUiWithTheme(null); + + assertThat(ui.getTheme(), is(nullValue())); + } +} diff --git a/shared/src/com/vaadin/shared/VBrowserDetails.java b/shared/src/com/vaadin/shared/VBrowserDetails.java index fa21bddc96..6e45d33e16 100644 --- a/shared/src/com/vaadin/shared/VBrowserDetails.java +++ b/shared/src/com/vaadin/shared/VBrowserDetails.java @@ -167,14 +167,11 @@ public class VBrowserDetails implements Serializable { if (userAgent.contains("windows ")) { os = OperatingSystem.WINDOWS; isWindowsPhone = userAgent.contains("windows phone"); + } else if (userAgent.contains("android")) { + os = OperatingSystem.ANDROID; + parseAndroidVersion(userAgent); } else if (userAgent.contains("linux")) { - if (userAgent.contains("android")) { - os = OperatingSystem.ANDROID; - parseAndroidVersion(userAgent); - } else { - os = OperatingSystem.LINUX; - - } + os = OperatingSystem.LINUX; } else if (userAgent.contains("macintosh") || userAgent.contains("mac osx") || userAgent.contains("mac os x")) { diff --git a/uitest/ivy.xml b/uitest/ivy.xml index 14c8bc6ce3..78171f9a9c 100644 --- a/uitest/ivy.xml +++ b/uitest/ivy.xml @@ -27,6 +27,8 @@ <dependency org="javax.validation" name="validation-api" rev="1.0.0.GA" conf="build,ide -> default,sources" /> + <dependency org="org.hibernate" name="hibernate-validator" + rev="4.2.0.Final" conf="build,ide -> default" /> <!-- Google App Engine --> <dependency org="com.google.appengine" name="appengine-api-1.0-sdk" rev="1.2.1" conf="build-provided,ide -> default" /> diff --git a/uitest/src/com/vaadin/tests/components/TooltipPosition.java b/uitest/src/com/vaadin/tests/components/TooltipPosition.java new file mode 100644 index 0000000000..30222722d9 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/TooltipPosition.java @@ -0,0 +1,70 @@ +/* + * 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; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.ui.Button; +import com.vaadin.ui.UI; +import com.vaadin.ui.VerticalLayout; + +/** + * This UI is used for testing that a tooltip is not positioned partially + * outside the browser window when there is enough space to display it. + * + * @author Vaadin Ltd + */ +public class TooltipPosition extends AbstractTestUI { + + public static final int NUMBER_OF_BUTTONS = 5; + + @Override + protected void setup(VaadinRequest request) { + // These tooltip delay settings can be removed once #13854 is resolved. + getTooltipConfiguration().setOpenDelay(0); + getTooltipConfiguration().setQuickOpenDelay(0); + getTooltipConfiguration().setCloseTimeout(1000); + + VerticalLayout layout = new VerticalLayout(); + layout.setSpacing(true); + layout.setHeight(UI.getCurrent().getPage().getBrowserWindowHeight(), + Unit.PIXELS); + addComponent(layout); + for (int i = 0; i < NUMBER_OF_BUTTONS; i++) { + Button button = new Button("Button"); + button.setDescription(generateTooltipText()); + layout.addComponent(button); + } + } + + private String generateTooltipText() { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < 50; i++) { + result.append("This is the line ").append(i) + .append(" of the long tooltip text.<br>"); + } + return result.toString(); + } + + @Override + public String getTestDescription() { + return "The tooltips of the buttons should not be clipped when there is enough space to display them."; + } + + @Override + public Integer getTicketNumber() { + return 15129; + } +} diff --git a/uitest/src/com/vaadin/tests/components/TooltipPositionTest.java b/uitest/src/com/vaadin/tests/components/TooltipPositionTest.java new file mode 100644 index 0000000000..4106374d64 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/TooltipPositionTest.java @@ -0,0 +1,173 @@ +/* + * 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; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Dimension; +import org.openqa.selenium.Point; +import org.openqa.selenium.StaleElementReferenceException; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebDriver.Window; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.support.ui.ExpectedCondition; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Tests that the tooltip is positioned so that it fits in the displayed area. + * + * @author Vaadin Ltd + */ +public class TooltipPositionTest extends MultiBrowserTest { + + @Test + public void testRegression_EmptyTooltipShouldNotBeAppearedDuringInitialization() + throws Exception { + openTestURL(); + + waitForElementVisible(By.cssSelector(".v-tooltip")); + WebElement tooltip = driver.findElement(By.cssSelector(".v-tooltip")); + + Assert.assertTrue( + "This init tooltip with text ' ' is present in the DOM and should be entirely outside the browser window", + isOutsideOfWindow(tooltip)); + } + + @Test + public void testTooltipPosition() throws Exception { + openTestURL(); + for (int i = 0; i < TooltipPosition.NUMBER_OF_BUTTONS; i++) { + ButtonElement button = $(ButtonElement.class).get(i); + // Move the mouse to display the tooltip. + Actions actions = new Actions(driver); + actions.moveToElement(button, 10, 10); + actions.build().perform(); + waitUntil(tooltipToBeInsideWindow(By.cssSelector(".v-tooltip"), + driver.manage().window())); + + if (i < TooltipPosition.NUMBER_OF_BUTTONS - 1) { + // Remove the tooltip by moving the mouse. + actions = new Actions(driver); + actions.moveByOffset(300, 0); + actions.build().perform(); + waitUntil(tooltipNotToBeShown(By.cssSelector(".v-tooltip"), + driver.manage().window())); + } + } + } + + /* + * An expectation for checking that the tooltip found by the given locator + * is present in the DOM and entirely inside the browser window. The + * coordinate of the top left corner of the window is supposed to be (0, 0). + */ + private ExpectedCondition<Boolean> tooltipToBeInsideWindow( + final By tooltipLocator, final Window window) { + return new ExpectedCondition<Boolean>() { + + @Override + public Boolean apply(WebDriver input) { + List<WebElement> elements = findElements(tooltipLocator); + if (elements.isEmpty()) { + return false; + } + WebElement element = elements.get(0); + try { + if (!element.isDisplayed()) { + return false; + } + Point topLeft = element.getLocation(); + int xLeft = topLeft.getX(); + int yTop = topLeft.getY(); + if (xLeft < 0 || yTop < 0) { + return false; + } + Dimension elementSize = element.getSize(); + int xRight = xLeft + elementSize.getWidth() - 1; + int yBottom = yTop + elementSize.getHeight() - 1; + Dimension browserSize = window.getSize(); + return xRight < browserSize.getWidth() + && yBottom < browserSize.getHeight(); + } catch (StaleElementReferenceException e) { + return false; + } + } + + @Override + public String toString() { + return "the tooltip to be displayed inside the window"; + } + }; + }; + + /* + * An expectation for checking that the tooltip found by the given locator + * is not shown in the window, even partially. The top left corner of window + * should have coordinates (0, 0). + */ + private ExpectedCondition<Boolean> tooltipNotToBeShown( + final By tooltipLocator, final Window window) { + return new ExpectedCondition<Boolean>() { + + @Override + public Boolean apply(WebDriver input) { + List<WebElement> elements = findElements(tooltipLocator); + if (elements.isEmpty()) { + return true; + } + WebElement tooltip = elements.get(0); + try { + return isOutsideOfWindow(tooltip); + } catch (StaleElementReferenceException e) { + return true; + } + } + + @Override + public String toString() { + return "the tooltip not to be displayed inside the window"; + } + + }; + } + + private boolean isOutsideOfWindow(WebElement tooltip) { + if (!tooltip.isDisplayed()) { + return true; + } + // The tooltip is shown, at least partially, if + // its intervals of both horizontal and vertical coordinates + // overlap those of the window. + Point topLeft = tooltip.getLocation(); + Dimension tooltipSize = tooltip.getSize(); + Dimension windowSize = driver.manage().window().getSize(); + int xLeft = topLeft.getX(); + int yTop = topLeft.getY(); + int xRight = xLeft + tooltipSize.getWidth() - 1; + int yBottom = yTop + tooltipSize.getHeight() - 1; + boolean overlapHorizontally = !(xRight < 0 || xLeft >= windowSize + .getWidth()); + boolean overlapVertically = !(yBottom < 0 || yTop >= windowSize + .getHeight()); + return !(overlapHorizontally && overlapVertically); + } +}
\ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/components/accordion/AccordionRemoveTabTest.java b/uitest/src/com/vaadin/tests/components/accordion/AccordionRemoveTabTest.java index f5651e0ada..1047c070c8 100644 --- a/uitest/src/com/vaadin/tests/components/accordion/AccordionRemoveTabTest.java +++ b/uitest/src/com/vaadin/tests/components/accordion/AccordionRemoveTabTest.java @@ -44,6 +44,19 @@ public class AccordionRemoveTabTest extends MultiBrowserTest { checkFirstItemHeight("On third tab"); } + @Test + public void testConsoleErrorOnSwitch() { + setDebug(true); + openTestURL(); + WebElement firstItem = driver.findElement(By + .className("v-accordion-item-first")); + WebElement caption = firstItem.findElement(By + .className("v-accordion-item-caption")); + caption.click(); + Assert.assertEquals("Errors present in console", 0, + findElements(By.className("SEVERE")).size()); + } + private void checkFirstItemHeight(String text) { WebElement firstItem = driver.findElement(By .className("v-accordion-item-first")); diff --git a/uitest/src/com/vaadin/tests/components/calendar/BeanItemContainerLongEventTest.java b/uitest/src/com/vaadin/tests/components/calendar/BeanItemContainerLongEventTest.java new file mode 100644 index 0000000000..0ec196f266 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/calendar/BeanItemContainerLongEventTest.java @@ -0,0 +1,55 @@ +/* + * 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.calendar; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.By; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Tests if long event which began before the view period is shown (#15242) + */ +public class BeanItemContainerLongEventTest extends MultiBrowserTest { + + @Override + protected String getDeploymentPath() { + return "/run/BeanItemContainerTestUI?restartApplication"; + } + + @Test + public void testEventDisplayedInWeekView() { + openTestURL(); + WebElement target = driver.findElements( + By.className("v-calendar-week-number")).get(1); + target.click(); + target = driver.findElement(By.className("v-calendar-event")); + Assert.assertEquals("Wrong event name", "Long event", target.getText()); + } + + @Test + public void testEventDisplayedInDayView() { + openTestURL(); + WebElement target = driver.findElements( + By.className("v-calendar-day-number")).get(5); + target.click(); + target = driver.findElement(By.className("v-calendar-event")); + Assert.assertEquals("Wrong event name", "Long event", target.getText()); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/calendar/BeanItemContainerTestUI.java b/uitest/src/com/vaadin/tests/components/calendar/BeanItemContainerTestUI.java index 83fc4a03cb..bda3b34875 100644 --- a/uitest/src/com/vaadin/tests/components/calendar/BeanItemContainerTestUI.java +++ b/uitest/src/com/vaadin/tests/components/calendar/BeanItemContainerTestUI.java @@ -17,6 +17,7 @@ package com.vaadin.tests.components.calendar; import java.util.Arrays; import java.util.Date; +import java.util.GregorianCalendar; import com.vaadin.data.fieldgroup.FieldGroup; import com.vaadin.data.fieldgroup.FieldGroup.CommitException; @@ -69,6 +70,13 @@ public class BeanItemContainerTestUI extends UI { table.setVisibleColumns(new Object[] { "caption", "description", "start", "end" }); content.addComponent(table); + + BasicEvent longEvent = new BasicEvent(); + longEvent.setCaption("Long event"); + longEvent.setAllDay(true); + longEvent.setStart(new GregorianCalendar(2000, 1, 3).getTime()); + longEvent.setEnd(new GregorianCalendar(2000, 2, 5).getTime()); + events.addBean(longEvent); } /** diff --git a/uitest/src/com/vaadin/tests/components/combobox/FilteringTurkishLocale.java b/uitest/src/com/vaadin/tests/components/combobox/FilteringTurkishLocale.java new file mode 100644 index 0000000000..ff7faf1965 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/combobox/FilteringTurkishLocale.java @@ -0,0 +1,57 @@ +/* + * 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 java.util.Arrays; +import java.util.Locale; + +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.ComboBox; +import com.vaadin.ui.NativeSelect; + +public class FilteringTurkishLocale extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + + final ComboBox comboBox = new ComboBox("Box", Arrays.asList( + "I without dot", "İ with dot")); + comboBox.setNullSelectionAllowed(false); + + NativeSelect localeSelect = new NativeSelect("Locale", Arrays.asList( + Locale.ENGLISH, new Locale("tr"))); + localeSelect.addValueChangeListener(new ValueChangeListener() { + @Override + public void valueChange(ValueChangeEvent event) { + comboBox.setLocale((Locale) event.getProperty().getValue()); + } + }); + localeSelect.setValue(Locale.ENGLISH); + + addComponents(localeSelect, comboBox); + } + + @Override + public String getDescription() { + return "When the Turkish locale is used," + + " filtering for 'i' should show the option with a dot" + + " while filtering for 'ı' should show the option witout a dot"; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/combobox/FilteringTurkishLocaleTest.java b/uitest/src/com/vaadin/tests/components/combobox/FilteringTurkishLocaleTest.java new file mode 100644 index 0000000000..d7f8e233ec --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/combobox/FilteringTurkishLocaleTest.java @@ -0,0 +1,80 @@ +/* + * 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 java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.testbench.By; +import com.vaadin.testbench.elements.ComboBoxElement; +import com.vaadin.testbench.elements.NativeSelectElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class FilteringTurkishLocaleTest extends MultiBrowserTest { + + @Test + public void testEnglishLocale() { + openTestURL(); + + setLocale("en"); + + List<String> suggestions = getFilterSuggestions("i"); + + Assert.assertEquals("Both suggestions should be present", 2, + suggestions.size()); + } + + @Test + public void testTurkishLocaleWithDot() { + openTestURL(); + + setLocale("tr"); + + List<String> suggestions = getFilterSuggestions("i"); + + Assert.assertEquals("There should be only one suggestion", 1, + suggestions.size()); + Assert.assertEquals("İ with dot", suggestions.get(0)); + } + + @Test + public void testTurkishLocaleWithoutDot() { + openTestURL(); + + setLocale("tr"); + + List<String> suggestions = getFilterSuggestions("ı"); + + Assert.assertEquals("There should be only one suggestion", 1, + suggestions.size()); + Assert.assertEquals("I without dot", suggestions.get(0)); + } + + private List<String> getFilterSuggestions(String string) { + ComboBoxElement comboBox = $(ComboBoxElement.class).first(); + comboBox.findElement(By.vaadin("#textbox")).sendKeys(string); + + return comboBox.getPopupSuggestions(); + } + + private void setLocale(String locale) { + NativeSelectElement selector = $(NativeSelectElement.class).first(); + selector.selectByText(locale); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithoutTemplate.java b/uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithoutTemplate.java new file mode 100644 index 0000000000..54949a053d --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithoutTemplate.java @@ -0,0 +1,44 @@ +/* + * 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.customlayout; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.CustomLayout; +import com.vaadin.ui.Label; + +public class CustomLayoutWithoutTemplate extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + CustomLayout cl = new CustomLayout("missing-layout-file.html"); + cl.addComponent(new Label("This Label should be visible."), "foo"); + cl.addComponent(new Button("And this Button too."), "bar"); + + addComponent(cl); + } + + @Override + protected String getTestDescription() { + return "Verify that CustomLayout renders child components even if the template is missing."; + } + + @Override + protected Integer getTicketNumber() { + return 8696; + } +} diff --git a/uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithoutTemplateTest.java b/uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithoutTemplateTest.java new file mode 100644 index 0000000000..695d9cceff --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithoutTemplateTest.java @@ -0,0 +1,43 @@ +/* + * 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.customlayout; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.testbench.ElementQuery; +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.CustomLayoutElement; +import com.vaadin.testbench.elements.LabelElement; +import com.vaadin.tests.tb3.SingleBrowserTest; + +public class CustomLayoutWithoutTemplateTest extends SingleBrowserTest { + + @Test + public void testChildComponents() { + openTestURL(); + + ElementQuery<CustomLayoutElement> customLayout = $(CustomLayoutElement.class); + + // Verify the Button and Label are rendered inside the CustomLayout. + assertTrue("Button was not rendered.", + customLayout.$(ButtonElement.class).exists()); + assertTrue("Label was not rendered.", customLayout + .$(LabelElement.class).exists()); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/datefield/DateFieldPopupClosing.java b/uitest/src/com/vaadin/tests/components/datefield/DateFieldPopupClosing.java new file mode 100644 index 0000000000..60508a30d4 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/datefield/DateFieldPopupClosing.java @@ -0,0 +1,43 @@ +/* + * 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 com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.DateField; + +public class DateFieldPopupClosing extends AbstractTestUI { + + static final String DATEFIELD_ID = "datefield"; + + @Override + protected void setup(VaadinRequest request) { + final DateField df = new DateField(); + df.setId(DATEFIELD_ID); + addComponent(df); + } + + @Override + protected String getTestDescription() { + return "DateField popup should be closed when click on popup button"; + } + + @Override + protected Integer getTicketNumber() { + return 14857; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/datefield/DateFieldPopupClosingTest.java b/uitest/src/com/vaadin/tests/components/datefield/DateFieldPopupClosingTest.java new file mode 100644 index 0000000000..9fd6fe82e2 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/datefield/DateFieldPopupClosingTest.java @@ -0,0 +1,81 @@ +package com.vaadin.tests.components.datefield; + +import java.io.IOException; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.support.ui.ExpectedCondition; +import org.openqa.selenium.support.ui.ExpectedConditions; + +import com.vaadin.testbench.elements.DateFieldElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class DateFieldPopupClosingTest extends MultiBrowserTest { + + @Test + public void testDateFieldPopupClosingLongClick() + throws InterruptedException, IOException { + openTestURL(); + + fastClickDateDatePickerButton(); + + assertThatPopupIsVisible(); + + longClickDateDatePickerButton(); + + assertThatPopupIsInvisible(); + } + + private void assertThatPopupIsVisible() { + waitUntil(ExpectedConditions.visibilityOfElementLocated(By + .className("v-datefield-popup"))); + } + + private void assertThatPopupIsInvisible() { + // ExpectedConditions.invisibilityOfElementLocated doesn't work + // with PhantomJS when running with a hub: + // https://code.google.com/p/selenium/issues/detail?id=5000 + // so we need to make our own. + + waitUntil(new ExpectedCondition<Boolean>() { + @Override + public Boolean apply(WebDriver input) { + try { + return !(findElement(By.className("v-datefield-popup")) + .isDisplayed()); + } catch (Exception e) { + return true; + } + } + + @Override + public String toString() { + // Timed out after 10 seconds waiting for ... + return "popup to not be visible"; + } + }); + } + + private void longClickDateDatePickerButton() { + WebElement button = getToggleButton(); + + new Actions(getDriver()).clickAndHold(button).perform(); + assertThatPopupIsInvisible(); + + new Actions(getDriver()).release(button).perform(); + } + + private WebElement getToggleButton() { + DateFieldElement dateField = $(DateFieldElement.class).first(); + + return dateField.findElement(By.tagName("button")); + } + + private void fastClickDateDatePickerButton() { + getToggleButton().click(); + } + +}
\ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/components/datefield/DateFieldPopupPosition.java b/uitest/src/com/vaadin/tests/components/datefield/DateFieldPopupPosition.java new file mode 100644 index 0000000000..4469ad3b1a --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/datefield/DateFieldPopupPosition.java @@ -0,0 +1,52 @@ +/* + * 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 com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.PopupDateField; + +/** + * Test UI for date field Popup calendar. + * + * @author Vaadin Ltd + */ +public abstract class DateFieldPopupPosition extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + HorizontalLayout layout = new HorizontalLayout(); + addComponent(layout); + Label gap = new Label(); + gap.setWidth(250, Unit.PIXELS); + layout.addComponent(gap); + PopupDateField field = new PopupDateField(); + layout.addComponent(field); + } + + @Override + protected Integer getTicketNumber() { + return 14757; + } + + @Override + protected String getTestDescription() { + return "Calendar popup should not placed on the top of text field when " + + "there is no space on bottom."; + } +} diff --git a/uitest/src/com/vaadin/tests/components/datefield/DateFieldPopupPositionTest.java b/uitest/src/com/vaadin/tests/components/datefield/DateFieldPopupPositionTest.java new file mode 100644 index 0000000000..f896519aae --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/datefield/DateFieldPopupPositionTest.java @@ -0,0 +1,68 @@ +/* + * 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 org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Dimension; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.elements.DateFieldElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Test for date field popup calendar position. + * + * @author Vaadin Ltd + */ +public abstract class DateFieldPopupPositionTest extends MultiBrowserTest { + + @Test + public void testPopupPosition() { + openTestURL(); + + int height = getFieldBottom() + 150; + adjustBrowserWindow(height); + + openPopup(); + + checkPopupPosition(); + } + + protected abstract void checkPopupPosition(); + + protected WebElement getPopup() { + return findElement(By.className("v-datefield-popup")); + } + + private void adjustBrowserWindow(int height) { + Dimension size = getDriver().manage().window().getSize(); + getDriver().manage().window() + .setSize(new Dimension(size.getWidth(), height)); + } + + private int getFieldBottom() { + DateFieldElement dateField = $(DateFieldElement.class).first(); + return dateField.getLocation().getY() + dateField.getSize().getHeight(); + } + + private void openPopup() { + findElement(By.className("v-datefield-button")).click(); + if (!isElementPresent(By.className("v-datefield-popup"))) { + findElement(By.className("v-datefield-button")).click(); + } + } +} diff --git a/uitest/src/com/vaadin/tests/components/datefield/DateRangeWithSqlDate.java b/uitest/src/com/vaadin/tests/components/datefield/DateRangeWithSqlDate.java new file mode 100644 index 0000000000..d3bc4267ec --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/datefield/DateRangeWithSqlDate.java @@ -0,0 +1,57 @@ +/* + * 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 com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.DateField; +import com.vaadin.ui.InlineDateField; + +import java.util.Locale; + +public class DateRangeWithSqlDate extends AbstractTestUI { + + // 2014-12-01 + private static final java.sql.Date startDate = new java.sql.Date( + 1417467822699L); + + // 2014-12-02 + private static final java.sql.Date endDate = new java.sql.Date( + 1417554763317L); + + @Override + protected void setup(VaadinRequest request) { + DateField df = new InlineDateField(); + df.setLocale(Locale.US); + df.setRangeStart(startDate); + df.setRangeEnd(endDate); + + df.setValue(startDate); + + addComponent(df); + } + + @Override + protected String getTestDescription() { + return "Test that java.sql.Date can be given to specify date range start and end dates."; + } + + @Override + protected Integer getTicketNumber() { + return 15342; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/datefield/DateRangeWithSqlDateTest.java b/uitest/src/com/vaadin/tests/components/datefield/DateRangeWithSqlDateTest.java new file mode 100644 index 0000000000..2352011585 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/datefield/DateRangeWithSqlDateTest.java @@ -0,0 +1,51 @@ +/* + * 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 java.util.List; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class DateRangeWithSqlDateTest extends MultiBrowserTest { + + @Test + public void testDateRange() { + openTestURL(); + + // Get all cells of the inline datefield. + List<WebElement> cells = driver.findElements(By + .className("v-inline-datefield-calendarpanel-day")); + + // Verify the range is rendered correctly. + assertCell(cells.get(0), "30", true); + assertCell(cells.get(1), "1", false); + assertCell(cells.get(2), "2", false); + assertCell(cells.get(3), "3", true); + } + + private void assertCell(WebElement cell, String text, boolean outsideRange) { + assertEquals(text, cell.getText()); + assertEquals(outsideRange, + cell.getAttribute("class").contains("outside-range")); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/datefield/DefaultDateFieldPopupPosition.java b/uitest/src/com/vaadin/tests/components/datefield/DefaultDateFieldPopupPosition.java new file mode 100644 index 0000000000..8e4de77837 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/datefield/DefaultDateFieldPopupPosition.java @@ -0,0 +1,27 @@ +/* + * 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; + +/** + * Test UI for date field Popup calendar in default theme. + * + * All UI initialization is defined in super class. + * + * @author Vaadin Ltd + */ +public class DefaultDateFieldPopupPosition extends DateFieldPopupPosition { + +} diff --git a/uitest/src/com/vaadin/tests/components/datefield/DefaultDateFieldPopupPositionTest.java b/uitest/src/com/vaadin/tests/components/datefield/DefaultDateFieldPopupPositionTest.java new file mode 100644 index 0000000000..61cc876a3f --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/datefield/DefaultDateFieldPopupPositionTest.java @@ -0,0 +1,43 @@ +/* + * 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 org.junit.Assert; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.elements.DateFieldElement; + +/** + * Test for date field popup calendar position in default theme. + * + * Test method is defined in super class. + * + * @author Vaadin Ltd + */ +public class DefaultDateFieldPopupPositionTest extends + DateFieldPopupPositionTest { + + @Override + protected void checkPopupPosition() { + DateFieldElement field = $(DateFieldElement.class).first(); + int right = field.getLocation().getX() + field.getSize().getWidth(); + WebElement popup = getPopup(); + + Assert.assertTrue("Calendar popup has wrong X coordinate=" + + popup.getLocation().getX() + " , right side of the field is " + + right, popup.getLocation().getX() >= right); + } +} diff --git a/uitest/src/com/vaadin/tests/components/datefield/ValoDateFieldPopupPosition.java b/uitest/src/com/vaadin/tests/components/datefield/ValoDateFieldPopupPosition.java new file mode 100644 index 0000000000..59ff6aa9e8 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/datefield/ValoDateFieldPopupPosition.java @@ -0,0 +1,30 @@ +/* + * 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 com.vaadin.annotations.Theme; + +/** + * Test UI for date field Popup calendar in Valo theme. + * + * All UI initialization is defined in super class. + * + * @author Vaadin Ltd + */ +@Theme("valo") +public class ValoDateFieldPopupPosition extends DateFieldPopupPosition { + +} diff --git a/uitest/src/com/vaadin/tests/components/datefield/ValoDateFieldPopupPositionTest.java b/uitest/src/com/vaadin/tests/components/datefield/ValoDateFieldPopupPositionTest.java new file mode 100644 index 0000000000..4009b9d991 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/datefield/ValoDateFieldPopupPositionTest.java @@ -0,0 +1,43 @@ +/* + * 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 org.junit.Assert; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.elements.DateFieldElement; + +/** + * Test for date field popup calendar position in Valo theme. + * + * Test method is defined in super class. + * + * @author Vaadin Ltd + */ +public class ValoDateFieldPopupPositionTest extends DateFieldPopupPositionTest { + + @Override + protected void checkPopupPosition() { + DateFieldElement field = $(DateFieldElement.class).first(); + WebElement popup = getPopup(); + int left = field.getLocation().getX(); + int popupRight = popup.getLocation().getX() + + popup.getSize().getWidth(); + + Assert.assertTrue("Calendar popup has wrong X coordinate=" + popupRight + + " , left side of the field is " + left, popupRight <= left); + } +} diff --git a/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragAndDropRelativeWidth.java b/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragAndDropRelativeWidth.java new file mode 100644 index 0000000000..90ec704a8c --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragAndDropRelativeWidth.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.components.draganddropwrapper; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.CssLayout; +import com.vaadin.ui.DragAndDropWrapper; +import com.vaadin.ui.DragAndDropWrapper.DragStartMode; +import com.vaadin.ui.Label; + +/** + * Test UI for DnD image element size + * + * @author Vaadin Ltd + */ +public class DragAndDropRelativeWidth extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + CssLayout layout = new CssLayout(); + layout.setWidth(300, Unit.PIXELS); + + Label label = new Label("drag source"); + label.addStyleName("drag-source"); + label.setWidth(100, Unit.PERCENTAGE); + DragAndDropWrapper wrapper = new DragAndDropWrapper(label); + wrapper.setWidth(100, Unit.PERCENTAGE); + wrapper.setDragStartMode(DragStartMode.COMPONENT); + + layout.addComponent(wrapper); + addComponent(layout); + } + + @Override + protected String getTestDescription() { + return "Set explicit size for drag image element using calclulated size from the source"; + } + + @Override + protected Integer getTicketNumber() { + return 14617; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragAndDropRelativeWidthTest.java b/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragAndDropRelativeWidthTest.java new file mode 100644 index 0000000000..9cb7a63046 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragAndDropRelativeWidthTest.java @@ -0,0 +1,57 @@ +/* + * 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.draganddropwrapper; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Dimension; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Test to check size of drag image element. + * + * @author Vaadin Ltd + */ +public class DragAndDropRelativeWidthTest extends MultiBrowserTest { + + @Test + public void testDragImageElementSize() { + openTestURL(); + + WebElement label = getDriver().findElement(By.className("drag-source")); + Dimension size = label.getSize(); + int height = size.getHeight(); + int width = size.getWidth(); + Actions actions = new Actions(getDriver()); + actions.moveToElement(label); + actions.clickAndHold(); + actions.moveByOffset(100, 100); + actions.build().perform(); + + WebElement dragImage = getDriver().findElement( + By.className("v-drag-element")); + + Assert.assertEquals("Drag image element height is unexpected", height, + dragImage.getSize().getHeight()); + Assert.assertEquals("Drag image element width is unexpected", width, + dragImage.getSize().getWidth()); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragStartModesTest.java b/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragStartModesTest.java index ba27ee293e..4e60b43ea2 100644 --- a/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragStartModesTest.java +++ b/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragStartModesTest.java @@ -40,7 +40,7 @@ public class DragStartModesTest extends MultiBrowserTest { new Actions(driver).moveToElement(draggable, 10, 10).clickAndHold() .moveByOffset(5, 0).perform(); new Actions(driver).moveToElement(dropTarget, 12, 10).perform(); - compareScreen("dragMode" + dragMode); + compareScreen("dragImageMode" + dragMode); new Actions(driver).release().perform(); } diff --git a/uitest/src/com/vaadin/tests/components/menubar/MenuBarSubmenusClosingValo.java b/uitest/src/com/vaadin/tests/components/menubar/MenuBarSubmenusClosingValo.java new file mode 100644 index 0000000000..88d89abbf4 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/menubar/MenuBarSubmenusClosingValo.java @@ -0,0 +1,60 @@ +package com.vaadin.tests.components.menubar; + +import com.vaadin.annotations.Theme; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.MenuBar; +import com.vaadin.ui.MenuBar.MenuItem; + +@Theme("valo") +public class MenuBarSubmenusClosingValo extends AbstractTestUI { + + private MenuItem edit; + private MenuItem file; + private MenuItem help; + + @Override + protected String getTestDescription() { + return "Tests that when moving mouse fast over menu items " + + "previous submenu popup closes before new submenu popup opens"; + } + + @Override + protected Integer getTicketNumber() { + return 15255; + } + + @Override + protected void setup(VaadinRequest request) { + // here we increase animation time to 1 second for to do auto testing + // possible + getPage().getStyles().add( + ".valo .v-menubar-popup[class*=\"animate-in\"] {" + + "-webkit-animation: valo-overlay-animate-in 1000ms; " + + "-moz-animation: valo-overlay-animate-in 1000ms; " + + "animation: valo-overlay-animate-in 1000ms;};"); + + getPage().getStyles().add( + ".valo .v-menubar-popup[class*=\"animate-out\"] {" + + "-webkit-animation: valo-animate-out-fade 1000ms; " + + "-moz-animation: valo-animate-out-fade 1000ms; " + + "animation: valo-animate-out-fade 1000ms;};"); + + MenuBar mb = new MenuBar(); + file = mb.addItem("File", null); + file.addItem("File1", null); + file.addItem("File2", null); + file.addItem("File3", null); + edit = mb.addItem("Edit", null); + edit.addItem("Edit1", null); + edit.addItem("Edit2", null); + edit.addItem("Edit3", null); + help = mb.addItem("Help", null); + help.addItem("Help1", null); + help.addItem("Help2", null); + MenuItem helpMenuItem = help.addItem("Help3", null); + helpMenuItem.addItem("SubHelp3", null); + + addComponent(mb); + } +} diff --git a/uitest/src/com/vaadin/tests/components/menubar/MenuBarSubmenusClosingValoTest.java b/uitest/src/com/vaadin/tests/components/menubar/MenuBarSubmenusClosingValoTest.java new file mode 100644 index 0000000000..b7ed88c9ca --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/menubar/MenuBarSubmenusClosingValoTest.java @@ -0,0 +1,72 @@ +/* + * 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.menubar; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.HasInputDevices; +import org.openqa.selenium.interactions.Mouse; +import org.openqa.selenium.internal.Locatable; + +import com.vaadin.testbench.By; +import com.vaadin.testbench.elements.MenuBarElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class MenuBarSubmenusClosingValoTest extends MultiBrowserTest { + + @Test + public void testEnableParentLayoutControlByKeyboard() { + openTestURL(); + + MenuBarElement menu = $(MenuBarElement.class).get(0); + menu.focus(); + menu.sendKeys(Keys.SPACE); + menu.sendKeys(Keys.DOWN); + + waitForElementPresent(By.className("v-menubar-popup")); + + menu.sendKeys(Keys.ARROW_RIGHT); + menu.sendKeys(Keys.ARROW_RIGHT); + + int count = driver.findElements(By.className("v-menubar-popup")).size(); + Assert.assertTrue("The count of open popups should be one", count == 1); + } + + @Test + public void testEnableParentLayoutControlByMouse() { + openTestURL(); + + Mouse mouse = ((HasInputDevices) getDriver()).getMouse(); + + List<WebElement> menuItemList = driver.findElements(By + .className("v-menubar-menuitem")); + + mouse.click(((Locatable) menuItemList.get(0)).getCoordinates()); + waitForElementPresent(By.className("v-menubar-popup")); + + mouse.mouseMove(((Locatable) menuItemList.get(1)).getCoordinates()); + mouse.mouseMove(((Locatable) menuItemList.get(2)).getCoordinates()); + + waitForElementPresent(By.className("v-menubar-popup")); + + int count = driver.findElements(By.className("v-menubar-popup")).size(); + Assert.assertTrue("The count of open popups should be one", count == 1); + } +} diff --git a/uitest/src/com/vaadin/tests/components/menubar/MenuTooltipTest.java b/uitest/src/com/vaadin/tests/components/menubar/MenuTooltipTest.java index 24025b9f39..091f7be954 100644 --- a/uitest/src/com/vaadin/tests/components/menubar/MenuTooltipTest.java +++ b/uitest/src/com/vaadin/tests/components/menubar/MenuTooltipTest.java @@ -49,6 +49,7 @@ public class MenuTooltipTest extends MultiBrowserTest { Coordinates elementCoordinates = getCoordinates($(MenuBarElement.class) .first()); + sleep(1000); Mouse mouse = ((HasInputDevices) getDriver()).getMouse(); diff --git a/uitest/src/com/vaadin/tests/components/notification/NotificationsWaiAriaTest.java b/uitest/src/com/vaadin/tests/components/notification/NotificationsWaiAriaTest.java index 6b517e9887..252efe2824 100644 --- a/uitest/src/com/vaadin/tests/components/notification/NotificationsWaiAriaTest.java +++ b/uitest/src/com/vaadin/tests/components/notification/NotificationsWaiAriaTest.java @@ -19,6 +19,7 @@ import org.junit.Assert; import org.junit.Test; import org.openqa.selenium.WebElement; +import com.vaadin.data.util.converter.StringToEnumConverter; import com.vaadin.shared.ui.ui.NotificationRole; import com.vaadin.testbench.By; import com.vaadin.testbench.elements.ButtonElement; @@ -57,7 +58,8 @@ public class NotificationsWaiAriaTest extends MultiBrowserTest { postfix.clear(); postfix.sendKeys("- press ESC to close"); - type.selectByText(NotificationRole.ALERT.toString()); + type.selectByText(StringToEnumConverter.enumToString( + NotificationRole.ALERT, null)); show.click(); waitForElementPresent(By.className("v-Notification")); @@ -83,7 +85,8 @@ public class NotificationsWaiAriaTest extends MultiBrowserTest { } catch (Exception e) { } - type.selectByText("STATUS"); + type.selectByText(StringToEnumConverter.enumToString( + NotificationRole.STATUS, null)); show.click(); waitForElementPresent(By.className("v-Notification")); diff --git a/uitest/src/com/vaadin/tests/components/select/EnumSelect.java b/uitest/src/com/vaadin/tests/components/select/EnumSelect.java new file mode 100644 index 0000000000..5976952f8c --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/select/EnumSelect.java @@ -0,0 +1,69 @@ +/* + * 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.select; + +import java.util.Locale; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.combobox.FilteringMode; +import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.ui.ComboBox; +import com.vaadin.ui.NativeSelect; +import com.vaadin.ui.Tree; + +public class EnumSelect extends AbstractTestUIWithLog { + + public enum Constant { + SOME_VALUE, SOME_OTHER_VALUE, FOO, BAR; + } + + @Override + protected void setup(VaadinRequest request) { + + setLocale(new Locale("fi", "FI")); + ComboBox cb = new ComboBox(); + cb.setFilteringMode(FilteringMode.CONTAINS); + for (Constant c : Constant.values()) { + cb.addItem(c); + } + addComponent(cb); + + NativeSelect ns = new NativeSelect(); + for (Constant c : Constant.values()) { + ns.addItem(c); + } + addComponent(ns); + + Tree t = new Tree(); + t.addItem(Constant.SOME_OTHER_VALUE); + t.addItem(2500.12); + t.setParent(2500.12, Constant.SOME_OTHER_VALUE); + + addComponent(t); + + } + + @Override + protected String getTestDescription() { + return "Test formatting captions with enum converters in selection components"; + } + + @Override + protected Integer getTicketNumber() { + return 11433; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/select/EnumSelectTest.java b/uitest/src/com/vaadin/tests/components/select/EnumSelectTest.java new file mode 100644 index 0000000000..c0429baa31 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/select/EnumSelectTest.java @@ -0,0 +1,61 @@ +/* + * 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.select; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.testbench.By; +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.testbench.elements.ComboBoxElement; +import com.vaadin.testbench.elements.NativeSelectElement; +import com.vaadin.tests.tb3.SingleBrowserTest; + +public class EnumSelectTest extends SingleBrowserTest { + + @Test + public void enumInNativeSelect() { + openTestURL(); + NativeSelectElement ns = $(NativeSelectElement.class).first(); + List<TestBenchElement> options = ns.getOptions(); + Assert.assertEquals("Some value", options.get(1).getText()); + Assert.assertEquals("Some other value", options.get(2).getText()); + } + + @Test + public void enumInComboBox() { + openTestURL(); + ComboBoxElement cb = $(ComboBoxElement.class).first(); + cb.openPopup(); + List<String> options = cb.getPopupSuggestions(); + Assert.assertEquals("Some value", options.get(1)); + Assert.assertEquals("Some other value", options.get(2)); + } + + @Test + public void enumInComboBoxFiltering() { + openTestURL(); + ComboBoxElement cb = $(ComboBoxElement.class).first(); + cb.findElement(By.vaadin("#textbox")).sendKeys(" other "); + List<String> options = cb.getPopupSuggestions(); + Assert.assertEquals("Only one item should match filter", 1, + options.size()); + Assert.assertEquals("Invalid option matched filter", + "Some other value", options.get(0)); + } +} diff --git a/uitest/src/com/vaadin/tests/components/splitpanel/HorizontalSplitPanelHeight.java b/uitest/src/com/vaadin/tests/components/splitpanel/HorizontalSplitPanelHeight.java new file mode 100644 index 0000000000..4da5430cb1 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/splitpanel/HorizontalSplitPanelHeight.java @@ -0,0 +1,87 @@ +/* + * 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.splitpanel; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.MarginInfo; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.HorizontalSplitPanel; +import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalSplitPanel; + +/** + * Test UI for horizontal split panel height. + * + * @author Vaadin Ltd + */ +public class HorizontalSplitPanelHeight extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + getLayout().setMargin(new MarginInfo(true, false, false, false)); + + HorizontalSplitPanel panel = new HorizontalSplitPanel(); + panel.setCaption("Horizontal 1 - no first component, label as second component"); + panel.setId("Horizontal 1"); + Label label = new Label("Label"); + label.addStyleName("target"); + panel.setSecondComponent(label); + + addComponent(panel); + + panel = new HorizontalSplitPanel(); + panel.setCaption("Horizontal 2 - button as first component, label as second component"); + panel.setId("Horizontal 2"); + label = new Label("Label"); + label.addStyleName("target"); + panel.setSecondComponent(label); + panel.setFirstComponent(new Button("button")); + + addComponent(panel); + + panel = new HorizontalSplitPanel(); + panel.setCaption("Horizontal 3 - fixed height, no first component, label as second component"); + panel.setId("Horizontal 3"); + label = new Label("Label"); + label.addStyleName("target"); + panel.setSecondComponent(label); + panel.setHeight(30, Unit.PIXELS); + + addComponent(panel); + + VerticalSplitPanel vPanel = new VerticalSplitPanel(); + vPanel.setCaption("Vertical 1 - no first component, label as second component"); + vPanel.setId("Vertical 1"); + vPanel.setHeight(100, Unit.PIXELS); + Label vLabel = new Label("Label"); + vLabel.addStyleName("target"); + vPanel.setSecondComponent(vLabel); + + addComponent(vPanel); + + } + + @Override + protected Integer getTicketNumber() { + return 15149; + } + + @Override + public String getTestDescription() { + return "Height of split panel should be greater than height of second component."; + } +} diff --git a/uitest/src/com/vaadin/tests/components/splitpanel/HorizontalSplitPanelHeightTest.java b/uitest/src/com/vaadin/tests/components/splitpanel/HorizontalSplitPanelHeightTest.java new file mode 100644 index 0000000000..0ceca66dd3 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/splitpanel/HorizontalSplitPanelHeightTest.java @@ -0,0 +1,71 @@ +/* + * 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.splitpanel; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Test for horizontal split panel height in case when only second component is + * set. + * + * @author Vaadin Ltd + */ +public class HorizontalSplitPanelHeightTest extends MultiBrowserTest { + + @Override + public void setup() throws Exception { + super.setup(); + + openTestURL(); + } + + @Test + public void testHorizontalWithoutFirstComponent() { + testSplitPanel("Horizontal 1"); + } + + @Test + public void testHorizontalWithFirstComponent() { + testSplitPanel("Horizontal 2"); + } + + @Test + public void testHorizontalWithFixedHeight() { + testSplitPanel("Horizontal 3"); + } + + @Test + public void testVerticalWithoutFirstComponent() { + testSplitPanel("Vertical 1"); + } + + private void testSplitPanel(String id) { + WebElement splitPanel = findElement(By.id(id)); + WebElement label = splitPanel.findElement(By.className("target")); + Assert.assertTrue(id + ": split panel height (" + + splitPanel.getSize().getHeight() + ") is less than " + + "height of second component (" + label.getSize().getHeight() + + ")", splitPanel.getSize().getHeight() >= label.getSize() + .getHeight()); + Assert.assertEquals("Label text in the second panel is not visible", + "Label", label.getText()); + } +} diff --git a/uitest/src/com/vaadin/tests/components/table/DelayedColumnLayouting.java b/uitest/src/com/vaadin/tests/components/table/DelayedColumnLayouting.java new file mode 100644 index 0000000000..c327ddb6f3 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/DelayedColumnLayouting.java @@ -0,0 +1,72 @@ +/* + * 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 com.vaadin.server.VaadinRequest; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.Table; +import com.vaadin.ui.UI; +import com.vaadin.ui.VerticalLayout; + +/** + * For tables that are contained in a layout, a delayed column layouting should + * not be visible (because it makes the column jump around). + * + * #15189 + * + * @author Vaadin Ltd + */ +public class DelayedColumnLayouting extends UI { + + @Override + protected void init(VaadinRequest request) { + VerticalLayout verticalLayout = new VerticalLayout(); + verticalLayout.setSizeFull(); + final VerticalLayout layout = new VerticalLayout(); + layout.setSizeFull(); + layout.setSpacing(true); + + Button reset = new Button("Recreate layout with contained table"); + verticalLayout.addComponent(reset); + reset.addClickListener(new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + fillLayout(layout); + } + }); + + fillLayout(layout); + + verticalLayout.addComponent(layout); + verticalLayout.setExpandRatio(layout, 1f); + + setContent(verticalLayout); + } + + private void fillLayout(VerticalLayout layout) { + layout.removeAllComponents(); + + Table table = new Table(); + table.setSizeFull(); + table.addContainerProperty("First", String.class, ""); + table.addContainerProperty("This column jumps", String.class, ""); + + layout.addComponent(table); + layout.setExpandRatio(table, 1f); + } +}
\ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/components/table/SetCurrentPageFirstItemIndex.html b/uitest/src/com/vaadin/tests/components/table/SetCurrentPageFirstItemIndex.html deleted file mode 100644 index 904f3b0470..0000000000 --- a/uitest/src/com/vaadin/tests/components/table/SetCurrentPageFirstItemIndex.html +++ /dev/null @@ -1,43 +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.SetCurrentPageFirstItemIndex?restartApplication</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runcomvaadintestscomponentstableSetCurrentPageFirstItemIndex::/VVerticalLayout[0]/Slot[1]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runcomvaadintestscomponentstableSetCurrentPageFirstItemIndex::/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=runcomvaadintestscomponentstableSetCurrentPageFirstItemIndex::/VVerticalLayout[0]/Slot[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[0]</td> - <td>6</td> -</tr> - -</tbody></table> -</body> -</html>
\ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/components/table/SetCurrentPageFirstItemIndexTest.java b/uitest/src/com/vaadin/tests/components/table/SetCurrentPageFirstItemIndexTest.java new file mode 100644 index 0000000000..8102f82834 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/SetCurrentPageFirstItemIndexTest.java @@ -0,0 +1,63 @@ +/* + * 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.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import junit.framework.Assert; + +import org.junit.Ignore; +import org.junit.Test; +import org.openqa.selenium.NoSuchElementException; + +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.TableElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * + * @since + * @author Vaadin Ltd + */ +@Ignore +// Enable after #15286 is fixed. +public class SetCurrentPageFirstItemIndexTest extends MultiBrowserTest { + + @Test + public void currentPageIndexChangesTwice() { + openTestURL(); + + ButtonElement button = $(ButtonElement.class).first(); + button.click(); // change to 20 + button.click(); // change to 5 + + // When failing, the index stays on 20. + assertThatRowIsVisible(5); + } + + private void assertThatRowIsVisible(int index) { + try { + TableElement table = $(TableElement.class).first(); + TestBenchElement cell = table.getCell(index, 0); + + assertThat(cell.getText(), is(Integer.toString(index + 1))); + } catch (NoSuchElementException e) { + Assert.fail(String.format("Can't locate row for index: %s", index)); + } + } + +} diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/FirstTabNotVisibleInTabsheet.java b/uitest/src/com/vaadin/tests/components/tabsheet/FirstTabNotVisibleInTabsheet.java new file mode 100644 index 0000000000..c21c702bd0 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/tabsheet/FirstTabNotVisibleInTabsheet.java @@ -0,0 +1,44 @@ +package com.vaadin.tests.components.tabsheet; + +import com.vaadin.annotations.VaadinServletConfiguration; +import com.vaadin.server.VaadinRequest; +import com.vaadin.server.VaadinServlet; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.*; + +import javax.servlet.annotation.WebServlet; + +@SuppressWarnings("serial") +public class FirstTabNotVisibleInTabsheet extends AbstractTestUI { + + private TabSheet.Tab firstTab; + + @Override + protected void setup(VaadinRequest request) { + TabSheet tabSheet = new TabSheet(); + tabSheet.setWidth("600px"); + + firstTab = tabSheet.addTab(new Label("first visible tab"), "first visible tab"); + + for (int i = 2; i < 10; i++) { + tabSheet.addTab(new Label("visible tab " + i), "visible tab " + i); + } + + addComponent(new VerticalLayout(tabSheet, new Button("Toggle first tab", new Button.ClickListener() { + @Override + public void buttonClick(Button.ClickEvent event) { + firstTab.setVisible(!firstTab.isVisible()); + } + }))); + } + + @Override + protected Integer getTicketNumber() { + return 14644; + } + + @Override + protected String getTestDescription() { + return "First tabsheet tab is not set visible back once it gets invisible"; + } +}
\ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/FirstTabNotVisibleInTabsheetTest.java b/uitest/src/com/vaadin/tests/components/tabsheet/FirstTabNotVisibleInTabsheetTest.java new file mode 100644 index 0000000000..e57651ba03 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/tabsheet/FirstTabNotVisibleInTabsheetTest.java @@ -0,0 +1,27 @@ +package com.vaadin.tests.components.tabsheet; + + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.TabSheetElement; +import com.vaadin.tests.tb3.MultiBrowserTest; +import junit.framework.Assert; +import org.junit.Test; + +public class FirstTabNotVisibleInTabsheetTest extends MultiBrowserTest { + @Test + public void testFirstTabIsVisibleAfterBeingInvisible() { + openTestURL(); + + toggleFirstTabVisibility(); + toggleFirstTabVisibility(); + + TabSheetElement tabSheet = $(TabSheetElement.class).first(); + + Assert.assertTrue("TabSheet should have first tab visible", + tabSheet.getTabCaptions().contains("first visible tab")); + } + + private void toggleFirstTabVisibility() { + $(ButtonElement.class).caption("Toggle first tab").first().click(); + } +} diff --git a/uitest/src/com/vaadin/tests/components/textfield/AlternatingTextFields.java b/uitest/src/com/vaadin/tests/components/textfield/AlternatingTextFields.java new file mode 100644 index 0000000000..3eda11d999 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/textfield/AlternatingTextFields.java @@ -0,0 +1,106 @@ +/* + * 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.textfield; + +import com.vaadin.event.FieldEvents.TextChangeEvent; +import com.vaadin.event.FieldEvents.TextChangeListener; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.TextField; +import com.vaadin.ui.VerticalLayout; + +/** + * When two TextFields repeatedly disable each other, ensure that also their + * input prompts are removed + * + * @since + * @author Vaadin Ltd + */ +public class AlternatingTextFields extends AbstractTestUI { + + public static final String FIRST_TEXTFIELD_INPUT_PROMPT = "Enter first data here"; + public static final String SECOND_TEXTFIELD_INPUT_PROMPT = "Enter second data here"; + + @Override + protected void setup(final VaadinRequest request) { + + VerticalLayout layout = new VerticalLayout(); + layout.setMargin(true); + layout.setSpacing(true); + + final TextField firstTextField = createTextField("First", + FIRST_TEXTFIELD_INPUT_PROMPT); + + final TextField secondTextField = createTextField("Second", + SECOND_TEXTFIELD_INPUT_PROMPT); + + addTextChangeListener(firstTextField, secondTextField); + addTextChangeListener(secondTextField, firstTextField); + + layout.addComponent(firstTextField); + layout.addComponent(secondTextField); + + addComponent(layout); + } + + private static TextField createTextField(String number, String inputPrompt) { + + String caption = " TextField with TextChangeListener"; + + TextField textField = new TextField(number + caption); + textField.setImmediate(true); + textField.setInputPrompt(inputPrompt); + + return textField; + } + + private void addTextChangeListener(TextField currentTextField, + final TextField otherTextField) { + + final String otherDefaultPrompt = otherTextField.getInputPrompt(); + currentTextField.addTextChangeListener(new TextChangeListener() { + + @Override + public void textChange(TextChangeEvent event) { + + String currentText = event.getText(); + + if (currentText.isEmpty() || currentText == null) { + // change other to default + + otherTextField.setInputPrompt(otherDefaultPrompt); + otherTextField.setEnabled(true); + } else { + // change other to empty + + otherTextField.setInputPrompt(null); + otherTextField.setEnabled(false); + } + + } + }); + } + + @Override + protected String getTestDescription() { + return "When two TextFields repeatedly disable each other, ensure that also their input prompts are removed"; + } + + @Override + protected Integer getTicketNumber() { + return 15144; + } +} diff --git a/uitest/src/com/vaadin/tests/components/textfield/AlternatingTextFieldsTest.java b/uitest/src/com/vaadin/tests/components/textfield/AlternatingTextFieldsTest.java new file mode 100644 index 0000000000..a7ee3fede2 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/textfield/AlternatingTextFieldsTest.java @@ -0,0 +1,212 @@ +/* + * 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.textfield; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.support.ui.ExpectedCondition; + +import com.vaadin.testbench.elements.TextFieldElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class AlternatingTextFieldsTest extends MultiBrowserTest { + + private String RANDOM_INPUT = "Some input here"; + + private List<TextFieldElement> textfields; + + @Test + public void testInputPrompt() { + openTestURL(); + + /* + * Starting positions + */ + + createTextFields(); + + // test that both input prompts exist in the beginning + ensureTextFieldHasInputPrompt(0); + ensureTextFieldHasInputPrompt(1); + + /* + * Write on and empty the first TextField + */ + + // select first input prompt + ensureSelectionClearsPrompt(0); + + // write on the first TextField + ensureWritingDisablesOther(0); + + // empty the text on the first TextField + ensureEmptyingAddsPromptAndEnablesOther(0); + + /* + * Write on and empty the second TextField + */ + + // now select the second input prompt + ensureSelectionClearsPrompt(1); + + // write on the second TextField + ensureWritingDisablesOther(1); + + // empty the text on the second TextField + ensureEmptyingAddsPromptAndEnablesOther(1); + + } + + private void ensureEmptyingAddsPromptAndEnablesOther(int index) { + // remove the text from the TextField + emptyTextField(index); + + // ensure that the TextField really is empty + ensureTextFieldEmpty(index); + + // ensure that the other TextField has again been enabled and has an + // input prompt + if (index == 0) { + ensureTextFieldIsEnabledAndHasInputPrompt(1); + } else { + ensureTextFieldIsEnabledAndHasInputPrompt(0); + } + } + + private void ensureWritingDisablesOther(int index) { + // write some text to the TextField + writeOnTextField(index); + + // ensure that the other TextField is disabled and has no input prompt + if (index == 0) { + ensureTextFieldDisabledAndEmpty(1); + } else { + ensureTextFieldDisabledAndEmpty(0); + } + } + + private void ensureSelectionClearsPrompt(int index) { + // select the TextField + textfields.get(index).click(); + + // check that the the prompt was removed + ensureTextFieldEmpty(index); + } + + /** + * Check that the TextField has no input prompt + * + * @since + * @param index + * The TextField to be inspected + */ + private void ensureTextFieldEmpty(int index) { + + assertEquals("TextField " + index + " was not empty,", "", textfields + .get(index).getValue()); + } + + /** + * Check that the TextField has been enabled and has correct input prompt + * + * @since + * @param index + * the TextField to be inspected + */ + private void ensureTextFieldIsEnabledAndHasInputPrompt(final int index) { + + waitUntil(new ExpectedCondition<Boolean>() { + + @Override + public Boolean apply(WebDriver input) { + return textfields.get(index).isEnabled(); + } + + @Override + public String toString() { + // Timed out after 10 seconds waiting for ... + return "TextField " + index + " to be enabled"; + } + }); + + ensureTextFieldHasInputPrompt(index); + } + + /** + * Check that the TextField has the correct input prompt + * + * @since + * @param index + * The TextField to be inspected + */ + private void ensureTextFieldHasInputPrompt(final int index) { + + if (index == 0) { + assertEquals("Incorrect or missing prompt,", + AlternatingTextFields.FIRST_TEXTFIELD_INPUT_PROMPT, + textfields.get(index).getValue()); + } else { + assertEquals("Incorrect or missing prompt,", + AlternatingTextFields.SECOND_TEXTFIELD_INPUT_PROMPT, + textfields.get(index).getValue()); + } + } + + /** + * Check that the TextField has been disabled and has no input prompt + * + * @since + * @param index + * The TextField to be inspected + */ + private void ensureTextFieldDisabledAndEmpty(final int index) { + + waitUntil(new ExpectedCondition<Boolean>() { + + @Override + public Boolean apply(WebDriver input) { + return !textfields.get(index).isEnabled(); + } + + @Override + public String toString() { + // Timed out after 10 seconds waiting for ... + return "TextField " + index + " to be disabled"; + } + }); + + ensureTextFieldEmpty(index); + } + + private void createTextFields() { + textfields = $(TextFieldElement.class).all(); + } + + private void writeOnTextField(int index) { + textfields.get(index).sendKeys(RANDOM_INPUT); + } + + private void emptyTextField(int index) { + for (int i = 0; i < 15; i++) { + textfields.get(index).sendKeys(Keys.BACK_SPACE); + } + } +} diff --git a/uitest/src/com/vaadin/tests/components/textfield/EnumTextField.java b/uitest/src/com/vaadin/tests/components/textfield/EnumTextField.java index 67b3b84688..99e08ae32d 100644 --- a/uitest/src/com/vaadin/tests/components/textfield/EnumTextField.java +++ b/uitest/src/com/vaadin/tests/components/textfield/EnumTextField.java @@ -31,6 +31,7 @@ public class EnumTextField extends AbstractTestUIWithLog { @Override protected void setup(VaadinRequest request) { final TextField tf = new TextField(); + tf.setNullRepresentation(""); tf.addValueChangeListener(new ValueChangeListener() { @Override diff --git a/uitest/src/com/vaadin/tests/components/textfield/EnumTextFieldTest.java b/uitest/src/com/vaadin/tests/components/textfield/EnumTextFieldTest.java index 113acee3a2..fe26fb7aad 100644 --- a/uitest/src/com/vaadin/tests/components/textfield/EnumTextFieldTest.java +++ b/uitest/src/com/vaadin/tests/components/textfield/EnumTextFieldTest.java @@ -27,8 +27,7 @@ public class EnumTextFieldTest extends SingleBrowserTest { public void validValues() { openTestURL(); $(TextFieldElement.class).first().clear(); - $(TextFieldElement.class).first().sendKeys("Value"); - $(TextFieldElement.class).first().sendKeys(Keys.TAB); + $(TextFieldElement.class).first().sendKeys("Value", Keys.TAB); Assert.assertEquals("3. Value (valid)", getLogRow(0)); $(TextFieldElement.class).first().clear(); @@ -41,13 +40,15 @@ public class EnumTextFieldTest extends SingleBrowserTest { $(TextFieldElement.class).first().sendKeys(Keys.TAB); Assert.assertEquals("7. The last value (valid)", getLogRow(0)); + $(TextFieldElement.class).first().clear(); + Assert.assertEquals("8. null (valid)", getLogRow(0)); + } @Test public void invalidValue() { openTestURL(); $(TextFieldElement.class).first().clear(); - Assert.assertEquals("2. (INVALID)", getLogRow(0)); $(TextFieldElement.class).first().sendKeys("bar"); $(TextFieldElement.class).first().sendKeys(Keys.TAB); diff --git a/uitest/src/com/vaadin/tests/components/treetable/MinimalWidthColumns.java b/uitest/src/com/vaadin/tests/components/treetable/MinimalWidthColumns.java new file mode 100644 index 0000000000..c4679f739b --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/treetable/MinimalWidthColumns.java @@ -0,0 +1,44 @@ +package com.vaadin.tests.components.treetable; + +import com.vaadin.annotations.Theme; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.TreeTable; + +@Theme("valo") +public class MinimalWidthColumns extends AbstractTestUI { + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#setup(com.vaadin.server. + * VaadinRequest) + */ + @Override + protected void setup(VaadinRequest request) { + TreeTable tt = new TreeTable(); + tt.addContainerProperty("Foo", String.class, ""); + tt.addContainerProperty("Bar", String.class, ""); + + Object item1 = tt.addItem(new Object[] { "f", "Bar" }, null); + Object item2 = tt.addItem(new Object[] { "Foo2", "Bar2" }, null); + + tt.setParent(item2, item1); + + tt.setColumnWidth("Foo", 0); + tt.setColumnWidth("Bar", 50); + tt.setWidth("300px"); + addComponent(tt); + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(15118); + } + + @Override + protected String getTestDescription() { + return "There should be no 1px discrepancy between vertical borders in headers and rows"; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/treetable/MinimalWidthColumnsTest.java b/uitest/src/com/vaadin/tests/components/treetable/MinimalWidthColumnsTest.java new file mode 100644 index 0000000000..46c2f397b6 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/treetable/MinimalWidthColumnsTest.java @@ -0,0 +1,31 @@ +/* + * 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 org.junit.Test; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class MinimalWidthColumnsTest extends MultiBrowserTest { + + @Test + public void testFor1pxDifference() throws Exception { + openTestURL(); + sleep(500); + compareScreen("onepixdifference"); + } + +} diff --git a/uitest/src/com/vaadin/tests/debug/PushVersionInfo.java b/uitest/src/com/vaadin/tests/debug/PushVersionInfo.java new file mode 100644 index 0000000000..d8c23a390f --- /dev/null +++ b/uitest/src/com/vaadin/tests/debug/PushVersionInfo.java @@ -0,0 +1,51 @@ +/* + * 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.debug; + +import org.atmosphere.util.Version; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.communication.PushMode; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Label; + +/** + * Test UI for PUSH version string in debug window. + * + * @author Vaadin Ltd + */ +public class PushVersionInfo extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + if (request.getParameter("enablePush") != null) { + getPushConfiguration().setPushMode(PushMode.AUTOMATIC); + Label label = new Label(Version.getRawVersion()); + label.addStyleName("atmosphere-version"); + addComponent(label); + } + } + + @Override + public String getDescription() { + return "Debug window shows Push version in info Tab."; + } + + @Override + protected Integer getTicketNumber() { + return 14904; + } +} diff --git a/uitest/src/com/vaadin/tests/debug/PushVersionInfoTest.java b/uitest/src/com/vaadin/tests/debug/PushVersionInfoTest.java new file mode 100644 index 0000000000..90ea645ab8 --- /dev/null +++ b/uitest/src/com/vaadin/tests/debug/PushVersionInfoTest.java @@ -0,0 +1,102 @@ +/* + * 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.debug; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.tests.annotations.TestCategory; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Test for PUSH version string in debug window. + * + * @author Vaadin Ltd + */ +@TestCategory("push") +public class PushVersionInfoTest extends MultiBrowserTest { + + @Test + public void testDisabledPush() { + setDebug(true); + openTestURL(); + + selectInfoTab(); + Assert.assertNull("Found push info server string for disabled Push", + getPushRowValue("Push server version")); + Assert.assertNull("Found push info client string for disabled Push", + getPushRowValue("Push client version")); + } + + @Test + public void testEnabledPush() { + setDebug(true); + openTestURL("enablePush=true"); + + selectInfoTab(); + WebElement pushRow = getPushRowValue("Push server version"); + String atmVersion = findElement(By.className("atmosphere-version")) + .getText(); + Assert.assertTrue("Push row doesn't contain Atmosphere version", + pushRow.getText().contains(atmVersion)); + String jsString = getPushRowValue("Push client version").getText(); + Assert.assertTrue( + "Push client version doesn't contain 'vaadin' string", + jsString.contains("vaadin")); + Assert.assertTrue( + "Push client version doesn't contain 'jquery' string", + jsString.contains("jquery")); + } + + private void selectInfoTab() { + if (isElementPresent(By.className("v-ie8"))) { + + int size = findElements(By.className("v-debugwindow-tab")).size(); + for (int i = 0; i < size; i++) { + WebElement tab = findElement(By + .className("v-debugwindow-tab-selected")); + String title = tab.getAttribute("title"); + if (title != null && title.startsWith("General information")) { + break; + } + Actions actions = new Actions(getDriver()); + actions.sendKeys(Keys.TAB); + actions.sendKeys(Keys.SPACE); + actions.build().perform(); + } + } else { + findElements(By.className("v-debugwindow-tab")).get(0).click(); + findElements(By.className("v-debugwindow-tab")).get(1).click(); + } + } + + private WebElement getPushRowValue(String key) { + List<WebElement> rows = findElements(By.className("v-debugwindow-row")); + for (WebElement row : rows) { + WebElement caption = row.findElement(By.className("caption")); + if (caption.getText().startsWith(key)) { + return row.findElement(By.className("value")); + } + } + return null; + } +} diff --git a/uitest/src/com/vaadin/tests/fieldgroup/BasicCrud.java b/uitest/src/com/vaadin/tests/fieldgroup/BasicCrud.java new file mode 100644 index 0000000000..be0368f4ae --- /dev/null +++ b/uitest/src/com/vaadin/tests/fieldgroup/BasicCrud.java @@ -0,0 +1,110 @@ +/* + * 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.fieldgroup; + +import com.vaadin.annotations.Theme; +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.data.fieldgroup.BeanFieldGroup; +import com.vaadin.data.fieldgroup.PropertyId; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.util.Person; +import com.vaadin.tests.util.PersonContainer; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Table; +import com.vaadin.ui.TextField; +import com.vaadin.ui.UI; +import com.vaadin.ui.VerticalLayout; + +@Theme("valo") +public class BasicCrud extends UI { + + private Form form; + + @Override + protected void init(VaadinRequest request) { + VerticalLayout main = new VerticalLayout(); + main.setMargin(true); + main.setSpacing(true); + final Table t = new Table(); + // t.setSelectionMode(SelectionMode.SINGLE); + t.setSelectable(true); + + PersonContainer c = PersonContainer.createWithTestData(); + + c.addBean(new Person("first", "Last", "email", "phone", "street", + 12332, "Turku")); + c.addBean(new Person("Foo", "Bar", "me@some.where", "123", + "homestreet 12", 10000, "Glasgow")); + t.setContainerDataSource(c); + // t.removeColumn("address"); + // t.setColumnOrder("firstName", "lastName", "email", "phoneNumber", + // "address.streetAddress", "address.postalCode", "address.city"); + t.setVisibleColumns("firstName", "lastName", "email", "phoneNumber", + "address.streetAddress", "address.postalCode", "address.city"); + + // t.addSelectionChangeListener(new SelectionChangeListener() { + // @Override + // public void selectionChange(SelectionChangeEvent event) { + // form.edit((Person) t.getSelectedRow()); + // } + // }); + t.addValueChangeListener(new ValueChangeListener() { + + @Override + public void valueChange(ValueChangeEvent event) { + form.edit((Person) t.getValue()); + } + }); + + form = new Form(); + + t.setSizeFull(); + + main.setSizeFull(); + main.addComponent(t); + main.addComponent(form); + main.setExpandRatio(t, 1); + setContent(main); + } + + public static class Form extends HorizontalLayout { + private TextField firstName = new TextField("First name"); + private TextField lastName = new TextField("Last name"); + private TextField email = new TextField("E-mail"); + @PropertyId("address.streetAddress") + private TextField streetAddress = new TextField("Street address"); + @PropertyId("address.postalCode") + private TextField postalCode = new TextField("Postal code"); + + BeanFieldGroup<Person> fieldGroup = new BeanFieldGroup<Person>( + Person.class); + + public Form() { + setSpacing(true); + setId("form"); + fieldGroup.bindMemberFields(this); + + // Stupid integer binding + postalCode.setNullRepresentation(""); + addComponents(firstName, lastName, email, streetAddress, postalCode); + } + + public void edit(Person p) { + fieldGroup.setItemDataSource(p); + } + } +} diff --git a/uitest/src/com/vaadin/tests/fieldgroup/BasicCrudTest.java b/uitest/src/com/vaadin/tests/fieldgroup/BasicCrudTest.java new file mode 100644 index 0000000000..a41725dbc9 --- /dev/null +++ b/uitest/src/com/vaadin/tests/fieldgroup/BasicCrudTest.java @@ -0,0 +1,68 @@ +/* + * 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.fieldgroup; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.testbench.elements.AbstractOrderedLayoutElement; +import com.vaadin.testbench.elements.TableElement; +import com.vaadin.testbench.elements.TextFieldElement; +import com.vaadin.tests.tb3.SingleBrowserTest; + +public class BasicCrudTest extends SingleBrowserTest { + + @Test + public void fieldsInitiallyEmpty() { + openTestURL(); + AbstractOrderedLayoutElement fieldsLayout = $( + AbstractOrderedLayoutElement.class).id("form"); + List<TextFieldElement> textFields = fieldsLayout.$( + TextFieldElement.class).all(); + + for (TextFieldElement e : textFields) { + Assert.assertEquals("TextField should be empty", "", e.getValue()); + } + } + + @Test + public void fieldsClearedOnDeselect() { + openTestURL(); + AbstractOrderedLayoutElement fieldsLayout = $( + AbstractOrderedLayoutElement.class).id("form"); + + // Select row + $(TableElement.class).first().getCell(2, 2).click(); + + List<TextFieldElement> textFields = fieldsLayout.$( + TextFieldElement.class).all(); + + for (TextFieldElement e : textFields) { + Assert.assertNotEquals("TextField should not be empty", "", + e.getValue()); + } + + // Deselect row + $(TableElement.class).first().getCell(2, 2).click(); + + for (TextFieldElement e : textFields) { + Assert.assertEquals("TextField should be empty", "", e.getValue()); + } + + } +} diff --git a/uitest/src/com/vaadin/tests/fieldgroup/MultipleValidationErrors.java b/uitest/src/com/vaadin/tests/fieldgroup/MultipleValidationErrors.java new file mode 100644 index 0000000000..5110bf6dcf --- /dev/null +++ b/uitest/src/com/vaadin/tests/fieldgroup/MultipleValidationErrors.java @@ -0,0 +1,72 @@ +package com.vaadin.tests.fieldgroup; + +import com.vaadin.data.Validator; +import com.vaadin.data.fieldgroup.FieldGroup; +import com.vaadin.data.util.BeanItem; +import com.vaadin.data.validator.BeanValidator; +import com.vaadin.server.AbstractErrorMessage; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Label; +import com.vaadin.ui.TextField; +import org.apache.commons.lang.StringEscapeUtils; + +public class MultipleValidationErrors extends AbstractTestUI { + + public static final String FIRST_NAME_NOT_NULL_VALIDATION_MESSAGE = "first name is null"; + public static final String LAST_NAME_NOT_NULL_VALIDATION_MESSAGE = "last name is null"; + public static final String FIRST_NAME_NOT_EMPTY_VALIDATION_MESSAGE = "first name is empty"; + public static final String LAST_NAME_NOT_EMPTY_VALIDATION_MESSAGE = "last name is empty"; + + @Override + protected void setup(VaadinRequest request) { + BeanItem<PersonBeanWithValidationAnnotations> item = new BeanItem<PersonBeanWithValidationAnnotations>( + new PersonBeanWithValidationAnnotations()); + final FieldGroup fieldGroup = new FieldGroup(item); + + bindTextField(item, fieldGroup, "First Name", "firstName"); + bindTextField(item, fieldGroup, "Last Name", "lastName"); + + final Label validationErrors = new Label(); + validationErrors.setId("validationErrors"); + addComponent(validationErrors); + + addButton("Submit", new Button.ClickListener() { + @Override + public void buttonClick(Button.ClickEvent event) { + validationErrors.setValue(""); + try { + fieldGroup.commit(); + } catch (FieldGroup.CommitException e) { + if (e.getCause() != null && e.getCause() instanceof Validator.InvalidValueException) { + validationErrors.setValue(StringEscapeUtils.unescapeHtml( + AbstractErrorMessage.getErrorMessageForException(e.getCause()).getFormattedHtmlMessage())); + } + } + + + } + }); + } + + private void bindTextField(BeanItem<PersonBeanWithValidationAnnotations> item, FieldGroup fieldGroup, + String caption, String propertyId) { + TextField textfield = new TextField(caption, item.getItemProperty(propertyId)); + textfield.addValidator(new BeanValidator(PersonBeanWithValidationAnnotations.class, propertyId)); + + fieldGroup.bind(textfield, propertyId); + + addComponent(textfield); + } + + @Override + protected Integer getTicketNumber() { + return 14742; + } + + @Override + protected String getTestDescription() { + return "All validation errors should be included when committing a field group."; + } +} diff --git a/uitest/src/com/vaadin/tests/fieldgroup/MultipleValidationErrorsTest.java b/uitest/src/com/vaadin/tests/fieldgroup/MultipleValidationErrorsTest.java new file mode 100644 index 0000000000..175b650be6 --- /dev/null +++ b/uitest/src/com/vaadin/tests/fieldgroup/MultipleValidationErrorsTest.java @@ -0,0 +1,37 @@ +package com.vaadin.tests.fieldgroup; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.LabelElement; +import com.vaadin.testbench.elements.TextFieldElement; +import com.vaadin.tests.tb3.MultiBrowserTest; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.MatcherAssert.assertThat; + +public class MultipleValidationErrorsTest extends MultiBrowserTest { + + private void commitTextFields() { + $(ButtonElement.class).caption("Submit").first().click(); + } + + private void clearTextField(String caption) { + TextFieldElement textField = $(TextFieldElement.class).caption(caption).first(); + textField.clear(); + } + + @Test + public void validationErrorsIncludeBothErrors() { + openTestURL(); + + clearTextField("First Name"); + clearTextField("Last Name"); + + commitTextFields(); + + String validationErrors = $(LabelElement.class).id("validationErrors").getText(); + + assertThat(validationErrors, containsString(MultipleValidationErrors.FIRST_NAME_NOT_EMPTY_VALIDATION_MESSAGE)); + assertThat(validationErrors, containsString(MultipleValidationErrors.LAST_NAME_NOT_EMPTY_VALIDATION_MESSAGE)); + } +} diff --git a/uitest/src/com/vaadin/tests/fieldgroup/PersonBeanWithValidationAnnotations.java b/uitest/src/com/vaadin/tests/fieldgroup/PersonBeanWithValidationAnnotations.java new file mode 100644 index 0000000000..5f81ee248b --- /dev/null +++ b/uitest/src/com/vaadin/tests/fieldgroup/PersonBeanWithValidationAnnotations.java @@ -0,0 +1,31 @@ +package com.vaadin.tests.fieldgroup; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.io.Serializable; + +public class PersonBeanWithValidationAnnotations implements Serializable { + @NotNull(message = MultipleValidationErrors.FIRST_NAME_NOT_NULL_VALIDATION_MESSAGE) + @Size(min = 1, message = MultipleValidationErrors.FIRST_NAME_NOT_EMPTY_VALIDATION_MESSAGE) + private String firstName; + + @NotNull(message = MultipleValidationErrors.LAST_NAME_NOT_NULL_VALIDATION_MESSAGE) + @Size(min = 1, message = MultipleValidationErrors.LAST_NAME_NOT_EMPTY_VALIDATION_MESSAGE) + private String lastName; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } +}
\ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/layouts/HorizontalLayoutWithLabelAndButton.java b/uitest/src/com/vaadin/tests/layouts/HorizontalLayoutWithLabelAndButton.java new file mode 100644 index 0000000000..9381f2caeb --- /dev/null +++ b/uitest/src/com/vaadin/tests/layouts/HorizontalLayoutWithLabelAndButton.java @@ -0,0 +1,43 @@ +/* + * 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.layouts; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.ui.Button; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; + +public class HorizontalLayoutWithLabelAndButton extends AbstractTestUIWithLog { + + @Override + protected void setup(VaadinRequest request) { + HorizontalLayout hl = new HorizontalLayout(); + hl.setSpacing(true); + hl.setWidth("100%"); + Label l = new Label(); + l.setCaption("POTUS Database"); + l.setSizeUndefined(); + + Button b = new Button("Add new"); + hl.addComponents(l, b); + b.setStyleName("primary"); + hl.setExpandRatio(b, 1); + + addComponent(hl); + } + +} diff --git a/uitest/src/com/vaadin/tests/minitutorials/v7a2/WidgetContainer.java b/uitest/src/com/vaadin/tests/minitutorials/v7a2/WidgetContainer.java index 8c14ba8bd7..850fa1044f 100644 --- a/uitest/src/com/vaadin/tests/minitutorials/v7a2/WidgetContainer.java +++ b/uitest/src/com/vaadin/tests/minitutorials/v7a2/WidgetContainer.java @@ -15,14 +15,12 @@ public class WidgetContainer extends AbstractComponentContainer { public void addComponent(Component c) { children.add(c); super.addComponent(c); - markAsDirty(); } @Override public void removeComponent(Component c) { children.remove(c); super.removeComponent(c); - markAsDirty(); } @Override diff --git a/uitest/src/com/vaadin/tests/navigator/NavigatorViewBlocksBackButtonAction.java b/uitest/src/com/vaadin/tests/navigator/NavigatorViewBlocksBackButtonAction.java new file mode 100644 index 0000000000..5c78a3f42a --- /dev/null +++ b/uitest/src/com/vaadin/tests/navigator/NavigatorViewBlocksBackButtonAction.java @@ -0,0 +1,128 @@ +package com.vaadin.tests.navigator; + +import com.vaadin.navigator.Navigator; +import com.vaadin.navigator.View; +import com.vaadin.navigator.ViewChangeListener; +import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; +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.Button.ClickListener; +import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.Window; + +public class NavigatorViewBlocksBackButtonAction extends AbstractTestUI { + + private Navigator navigator; + + protected static final String LABEL_MAINVIEW_ID = "LABEL_MAINVIEW_ID"; + protected static final String LABEL_PROMPTEDVIEW_ID = "LABEL_PROMPTEDVIEW_ID"; + + @Override + protected void setup(VaadinRequest request) { + navigator = new Navigator(this, this); + navigator.addView(MainView.NAME, new MainView()); + navigator.addView(ViewWithPromptedLeave.NAME, + new ViewWithPromptedLeave()); + navigator.navigateTo(MainView.NAME); + } + + class MainView extends VerticalLayout implements View { + + public static final String NAME = "mainview"; + + public MainView() { + Label label = new Label("MainView content"); + label.setId(LABEL_MAINVIEW_ID); + addComponent(label); + + Button buttonNavToAnotherView = new Button( + "Navigate to another view", new ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + navigator.navigateTo(ViewWithPromptedLeave.NAME); + } + }); + addComponent(buttonNavToAnotherView); + } + + @Override + public void enter(ViewChangeEvent event) { + } + + } + + class ViewWithPromptedLeave extends VerticalLayout implements View, + ViewChangeListener { + + public static final String NAME = "prompted"; + + protected boolean okToLeave; + + public ViewWithPromptedLeave() { + Label label = new Label("ViewWithPromptedLeave content"); + label.setId(LABEL_PROMPTEDVIEW_ID); + addComponent(label); + addComponent(new Label( + "Try to navigate back to first view with browser back button.")); + } + + @Override + public void enter(ViewChangeEvent event) { + event.getNavigator().addViewChangeListener(this); + } + + @Override + public boolean beforeViewChange(final ViewChangeEvent event) { + if (okToLeave) { + okToLeave = false; + return true; + } else { + final Window confirmationWindow = new Window("Confirm"); + confirmationWindow.setModal(true); + confirmationWindow.setClosable(true); + + VerticalLayout confirmationWindowLayout = new VerticalLayout(); + confirmationWindow.setContent(confirmationWindowLayout); + confirmationWindowLayout.setMargin(true); + confirmationWindowLayout.setSpacing(true); + confirmationWindowLayout.addComponent(new Label( + "Really exit this view?")); + confirmationWindowLayout.addComponent(new Button("Yeah, sure!", + new Button.ClickListener() { + + @Override + public void buttonClick(ClickEvent buttonEvent) { + okToLeave = true; + getUI().removeWindow(confirmationWindow); + event.getNavigator().navigateTo( + event.getViewName() + "/" + + event.getParameters()); + } + })); + getUI().addWindow(confirmationWindow); + return false; + } + } + + @Override + public void afterViewChange(ViewChangeEvent event) { + if (event.getNewView() != this) { + event.getNavigator().removeViewChangeListener(this); + } + } + } + + @Override + protected String getTestDescription() { + return "URL should not be changed when view blocks navigating away from view using the browser's Back-button"; + } + + @Override + protected Integer getTicketNumber() { + return 10901; + } +}
\ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/navigator/NavigatorViewBlocksBackButtonActionTest.java b/uitest/src/com/vaadin/tests/navigator/NavigatorViewBlocksBackButtonActionTest.java new file mode 100644 index 0000000000..84abdca24b --- /dev/null +++ b/uitest/src/com/vaadin/tests/navigator/NavigatorViewBlocksBackButtonActionTest.java @@ -0,0 +1,95 @@ +/* + * 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.navigator; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class NavigatorViewBlocksBackButtonActionTest extends MultiBrowserTest { + + @Test + public void testIfConfirmBack() { + openTestURL(); + + // keep URL of main view + final String initialUrl = driver.getCurrentUrl(); + + // do it 2 times to verify that login is not broken after first time + for (int i = 0; i < 2; i++) { + // go to prompted view + WebElement button = $(ButtonElement.class).first(); + button.click(); + + // click back button + driver.navigate().back(); + + // confirm "go back by clicking confirm button + WebElement buttonConfirmView = $(ButtonElement.class).first(); + buttonConfirmView.click(); + + // verify we are in main view and url is correct + waitForElementPresent(By + .id(NavigatorViewBlocksBackButtonAction.LABEL_MAINVIEW_ID)); + String currentUrl = driver.getCurrentUrl(); + assertEquals( + "Current URL should be equal to initial main view URL", + initialUrl, currentUrl); + } + } + + @Test + public void testIfCancelBack() { + openTestURL(); + + // go to prompted view + WebElement button = $(ButtonElement.class).first(); + button.click(); + + // keep URL of prompted view + final String initialPromptedUrl = driver.getCurrentUrl(); + + // click back button + driver.navigate().back(); + + // verify url is correct (is not changed) + waitForElementPresent(By + .id(NavigatorViewBlocksBackButtonAction.LABEL_PROMPTEDVIEW_ID)); + String currentUrl = driver.getCurrentUrl(); + assertEquals( + "Current URL should be equal to initial prompted view URL", + initialPromptedUrl, currentUrl); + + WebElement cancelButton = driver.findElement(By + .className("v-window-closebox")); + + // click cancel button + cancelButton.click(); + + // verify we leave in prompted view and url is correct + waitForElementPresent(By + .id(NavigatorViewBlocksBackButtonAction.LABEL_PROMPTEDVIEW_ID)); + currentUrl = driver.getCurrentUrl(); + assertEquals( + "Current URL should be equal to initial prompted view URL", + initialPromptedUrl, currentUrl); + } +} diff --git a/uitest/src/com/vaadin/tests/push/PushConfigurationLongPollingTest.java b/uitest/src/com/vaadin/tests/push/PushConfigurationLongPollingTest.java index a04d569e05..1d5ead7d98 100644 --- a/uitest/src/com/vaadin/tests/push/PushConfigurationLongPollingTest.java +++ b/uitest/src/com/vaadin/tests/push/PushConfigurationLongPollingTest.java @@ -18,11 +18,7 @@ package com.vaadin.tests.push; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.MatcherAssert.assertThat; -import java.util.List; - import org.junit.Test; -import org.openqa.selenium.remote.DesiredCapabilities; -import org.openqa.selenium.support.ui.Select; public class PushConfigurationLongPollingTest extends PushConfigurationTest { @@ -30,13 +26,13 @@ public class PushConfigurationLongPollingTest extends PushConfigurationTest { public void testLongPolling() throws InterruptedException { openDebugLogTab(); - new Select(getTransportSelect()).selectByVisibleText("LONG_POLLING"); + getTransportSelect().selectByText("Long polling"); assertThat(getStatusText(), containsString("fallbackTransport: long-polling")); assertThat(getStatusText(), containsString("transport: long-polling")); clearDebugMessages(); - new Select(getPushModeSelect()).selectByVisibleText("AUTOMATIC"); + getPushModeSelect().selectByText("Automatic"); waitForDebugMessage("Push connection established using long-polling", 10); waitForServerCounterToUpdate(); diff --git a/uitest/src/com/vaadin/tests/push/PushConfigurationStreamingTest.java b/uitest/src/com/vaadin/tests/push/PushConfigurationStreamingTest.java index f5c015ad12..202db8d6b7 100644 --- a/uitest/src/com/vaadin/tests/push/PushConfigurationStreamingTest.java +++ b/uitest/src/com/vaadin/tests/push/PushConfigurationStreamingTest.java @@ -15,25 +15,24 @@ */ package com.vaadin.tests.push; -import org.junit.Test; -import org.openqa.selenium.support.ui.Select; - import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.MatcherAssert.assertThat; +import org.junit.Test; + public class PushConfigurationStreamingTest extends PushConfigurationTest { @Test public void testStreaming() throws InterruptedException { openDebugLogTab(); - new Select(getTransportSelect()).selectByVisibleText("STREAMING"); + getTransportSelect().selectByText("Streaming"); assertThat(getStatusText(), containsString("fallbackTransport: long-polling")); assertThat(getStatusText(), containsString("transport: streaming")); clearDebugMessages(); - new Select(getPushModeSelect()).selectByVisibleText("AUTOMATIC"); + getPushModeSelect().selectByText("Automatic"); waitForDebugMessage("Push connection established using streaming", 10); waitForServerCounterToUpdate(); diff --git a/uitest/src/com/vaadin/tests/push/PushConfigurationTest.java b/uitest/src/com/vaadin/tests/push/PushConfigurationTest.java index bb5b420259..396160cc7d 100644 --- a/uitest/src/com/vaadin/tests/push/PushConfigurationTest.java +++ b/uitest/src/com/vaadin/tests/push/PushConfigurationTest.java @@ -20,8 +20,8 @@ import static org.junit.Assert.assertEquals; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedCondition; -import org.openqa.selenium.support.ui.Select; +import com.vaadin.testbench.elements.NativeSelectElement; import com.vaadin.tests.annotations.TestCategory; import com.vaadin.tests.tb3.MultiBrowserTest; @@ -49,7 +49,7 @@ abstract class PushConfigurationTest extends MultiBrowserTest { } protected void disablePush() throws InterruptedException { - new Select(getPushModeSelect()).selectByVisibleText("DISABLED"); + getPushModeSelect().selectByText("Disabled"); int counter = getServerCounter(); sleep(2000); @@ -57,12 +57,12 @@ abstract class PushConfigurationTest extends MultiBrowserTest { getServerCounter()); } - protected WebElement getPushModeSelect() { - return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VNativeSelect[0]/domChild[0]"); + protected NativeSelectElement getPushModeSelect() { + return $(NativeSelectElement.class).caption("Push mode").first(); } - protected WebElement getTransportSelect() { - return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[1]/VNativeSelect[0]/domChild[0]"); + protected NativeSelectElement getTransportSelect() { + return $(NativeSelectElement.class).caption("Transport").first(); } protected int getServerCounter() { diff --git a/uitest/src/com/vaadin/tests/push/PushConfigurationWebSocketTest.java b/uitest/src/com/vaadin/tests/push/PushConfigurationWebSocketTest.java index c9a813fac0..475fa2165f 100644 --- a/uitest/src/com/vaadin/tests/push/PushConfigurationWebSocketTest.java +++ b/uitest/src/com/vaadin/tests/push/PushConfigurationWebSocketTest.java @@ -23,7 +23,6 @@ import java.util.List; import org.junit.Test; import org.openqa.selenium.remote.DesiredCapabilities; -import org.openqa.selenium.support.ui.Select; public class PushConfigurationWebSocketTest extends PushConfigurationTest { @@ -40,8 +39,8 @@ public class PushConfigurationWebSocketTest extends PushConfigurationTest { @Test public void testWebsocket() throws InterruptedException { - new Select(getTransportSelect()).selectByVisibleText("WEBSOCKET"); - new Select(getPushModeSelect()).selectByVisibleText("AUTOMATIC"); + getTransportSelect().selectByText("Websocket"); + getPushModeSelect().selectByText("Automatic"); assertThat(getStatusText(), containsString("fallbackTransport: long-polling")); diff --git a/uitest/src/com/vaadin/tests/push/PushConfigurator.java b/uitest/src/com/vaadin/tests/push/PushConfigurator.java index 5a45ab7206..7da58af1da 100644 --- a/uitest/src/com/vaadin/tests/push/PushConfigurator.java +++ b/uitest/src/com/vaadin/tests/push/PushConfigurator.java @@ -87,11 +87,9 @@ public class PushConfigurator extends VerticalLayout { pushMode.addItem(PushMode.AUTOMATIC); for (Transport t : Transport.values()) { - transport.addItem(t.toString()); - fallbackTransport.addItem(t.toString()); + transport.addItem(t); + fallbackTransport.addItem(t); } - transport.addItem(""); - fallbackTransport.addItem(""); pushMode.setImmediate(true); transport.setImmediate(true); @@ -124,7 +122,7 @@ public class PushConfigurator extends VerticalLayout { transport.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { - Transport t = Transport.valueOf((String) transport.getValue()); + Transport t = (Transport) transport.getValue(); ui.getPushConfiguration().setTransport(t); refreshStatus(); } @@ -133,8 +131,7 @@ public class PushConfigurator extends VerticalLayout { fallbackTransport.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { - Transport t = Transport.valueOf((String) fallbackTransport - .getValue()); + Transport t = (Transport) fallbackTransport.getValue(); ui.getPushConfiguration().setFallbackTransport(t); refreshStatus(); } diff --git a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java index 76b851fd23..b5a345bd30 100644 --- a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java +++ b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java @@ -32,7 +32,6 @@ import java.util.Collections; import java.util.List; import java.util.NoSuchElementException; -import com.vaadin.testbench.elements.TableElement; import org.apache.commons.io.IOUtils; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; @@ -69,6 +68,7 @@ import com.vaadin.testbench.TestBenchDriverProxy; import com.vaadin.testbench.TestBenchElement; import com.vaadin.testbench.TestBenchTestCase; import com.vaadin.testbench.elements.LabelElement; +import com.vaadin.testbench.elements.TableElement; import com.vaadin.testbench.elements.VerticalLayoutElement; import com.vaadin.tests.components.AbstractTestUIWithLog; import com.vaadin.tests.tb3.MultiBrowserTest.Browser; @@ -257,7 +257,7 @@ public abstract class AbstractTB3Test extends TestBenchTestCase { @Override public Object apply(WebDriver input) { try { - return table.getCell(row, 0) != null; + return table.getCell(row, 0) != null; } catch (NoSuchElementException e) { return false; } @@ -266,7 +266,8 @@ public abstract class AbstractTB3Test extends TestBenchTestCase { } protected void scrollTable(TableElement table, int rows, int rowToWait) { - testBenchElement(table.findElement(By.className("v-scrollable"))).scroll(rows * 30); + testBenchElement(table.findElement(By.className("v-scrollable"))) + .scroll(rows * 30); waitUntilRowIsVisible(table, rowToWait); } @@ -430,6 +431,11 @@ public abstract class AbstractTB3Test extends TestBenchTestCase { @After public void tearDown() throws Exception { if (driver != null) { + try { + openTestURL("&closeApplication"); + } catch (Exception e) { + e.printStackTrace(); + } driver.quit(); } driver = null; diff --git a/uitest/src/com/vaadin/tests/themes/chameleon/ChameleonNotification.java b/uitest/src/com/vaadin/tests/themes/chameleon/ChameleonNotification.java new file mode 100644 index 0000000000..efb953530c --- /dev/null +++ b/uitest/src/com/vaadin/tests/themes/chameleon/ChameleonNotification.java @@ -0,0 +1,30 @@ +package com.vaadin.tests.themes.chameleon; + +import com.vaadin.annotations.Theme; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Notification; +import com.vaadin.ui.themes.ChameleonTheme; + +@Theme(ChameleonTheme.THEME_NAME) +public class ChameleonNotification extends AbstractTestUI { + @Override + protected void setup(VaadinRequest request) { + + + addButton("Notification", new Button.ClickListener() { + @Override + public void buttonClick(Button.ClickEvent event) { + Notification notification = new Notification("Notification"); + notification.setDelayMsec(30000); + notification.show(getUI().getPage()); + } + }); + } + + @Override + protected Integer getTicketNumber() { + return 15351; + } +} diff --git a/uitest/src/com/vaadin/tests/themes/chameleon/ChameleonNotificationTest.java b/uitest/src/com/vaadin/tests/themes/chameleon/ChameleonNotificationTest.java new file mode 100644 index 0000000000..ef41ef3df9 --- /dev/null +++ b/uitest/src/com/vaadin/tests/themes/chameleon/ChameleonNotificationTest.java @@ -0,0 +1,25 @@ +package com.vaadin.tests.themes.chameleon; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.NotificationElement; +import com.vaadin.tests.tb3.MultiBrowserTest; +import org.junit.Test; + +import java.io.IOException; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; + +public class ChameleonNotificationTest extends MultiBrowserTest { + @Test + public void gradientPathIsCorrect() throws IOException { + openTestURL(); + $(ButtonElement.class).first().click(); + + NotificationElement notificationElement + = $(NotificationElement.class).first(); + + assertThat(notificationElement.getCssValue("background-image"), + containsString("chameleon/img/grad")); + } +}
\ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/themes/valo/ButtonsAndLinks.java b/uitest/src/com/vaadin/tests/themes/valo/ButtonsAndLinks.java index e66cd2668b..9ed48896eb 100644 --- a/uitest/src/com/vaadin/tests/themes/valo/ButtonsAndLinks.java +++ b/uitest/src/com/vaadin/tests/themes/valo/ButtonsAndLinks.java @@ -178,6 +178,11 @@ public class ButtonsAndLinks extends VerticalLayout implements View { link.setIcon(testIcon.get()); link.addStyleName("large"); row.addComponent(link); + + link = new Link("Disabled", new ExternalResource("https://vaadin.com")); + link.setIcon(testIcon.get()); + link.setEnabled(false); + row.addComponent(link); } @Override diff --git a/uitest/src/com/vaadin/tests/themes/valo/CheckBoxes.java b/uitest/src/com/vaadin/tests/themes/valo/CheckBoxes.java index c7a2610a21..c79447bd86 100644 --- a/uitest/src/com/vaadin/tests/themes/valo/CheckBoxes.java +++ b/uitest/src/com/vaadin/tests/themes/valo/CheckBoxes.java @@ -79,6 +79,11 @@ public class CheckBoxes extends VerticalLayout implements View { check.addStyleName("large"); row.addComponent(check); + check = new CheckBox("Disabled", true); + check.setEnabled(false); + check.setIcon(testIcon.get()); + row.addComponent(check); + h1 = new Label("Option Groups"); h1.addStyleName("h1"); addComponent(h1); @@ -184,6 +189,17 @@ public class CheckBoxes extends VerticalLayout implements View { options.setItemIcon(two, testIcon.get()); options.setItemIcon("Option Three", testIcon.get()); row.addComponent(options); + + options = new OptionGroup("Disabled items"); + options.setEnabled(false); + options.addItem("Option One"); + options.addItem("Option Two"); + options.addItem("Option Three"); + options.select("Option One"); + options.setItemIcon("Option One", testIcon.get()); + options.setItemIcon("Option Two", testIcon.get()); + options.setItemIcon("Option Three", testIcon.get(true)); + row.addComponent(options); } @Override diff --git a/uitest/src/com/vaadin/tests/themes/valo/ModalWindowTest.java b/uitest/src/com/vaadin/tests/themes/valo/ModalWindowTest.java new file mode 100644 index 0000000000..b97ce43ed6 --- /dev/null +++ b/uitest/src/com/vaadin/tests/themes/valo/ModalWindowTest.java @@ -0,0 +1,34 @@ +package com.vaadin.tests.themes.valo; + +import com.vaadin.testbench.By; +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.tests.ModalWindow; +import com.vaadin.tests.tb3.SingleBrowserTest; +import org.junit.Test; +import org.openqa.selenium.WebElement; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class ModalWindowTest extends SingleBrowserTest { + + @Override + protected Class<?> getUIClass() { + return ModalWindow.class; + } + + @Test + public void modalAnimationsAreDisabled() { + openTestURL("theme=tests-valo-disabled-animations"); + + openModalWindow(); + + WebElement modalityCurtain = findElement(By.className("v-window-modalitycurtain")); + + assertThat(modalityCurtain.getCssValue("-webkit-animation-name"), is("none")); + } + + private void openModalWindow() { + $(ButtonElement.class).get(1).click(); + } +}
\ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUITest.java b/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUITest.java index 92cb837b38..13b0c7144c 100644 --- a/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUITest.java +++ b/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUITest.java @@ -39,7 +39,7 @@ public class ValoThemeUITest extends MultiBrowserTest { public void buttonsLinks() throws Exception { openTestURL("test"); open("Buttons & Links", "Buttons"); - compareScreen("buttonsLinks"); + compareScreen("buttonsLinks_with_disabled"); } @Test @@ -85,7 +85,7 @@ public class ValoThemeUITest extends MultiBrowserTest { public void checkboxes() throws Exception { openTestURL("test"); open("Check Boxes & Option Groups", "Check Boxes"); - compareScreen("checkboxes"); + compareScreen("checkboxes_with_disabled"); } @Test |