extract and re-use
[tapestry-5.git] / tapestry-core / src / test / java / org / apache / tapestry5 / integration / app1 / FormTests.java
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License.
12
13 package org.apache.tapestry5.integration.app1;
14
15 import java.text.SimpleDateFormat;
16 import java.util.Date;
17
18 import org.apache.tapestry5.corelib.components.Form;
19 import org.openqa.selenium.By;
20 import org.openqa.selenium.WebElement;
21 import org.openqa.selenium.support.ui.ExpectedCondition;
22 import org.openqa.selenium.support.ui.ExpectedConditions;
23 import org.testng.annotations.Test;
24
25 /**
26 * Tests for the {@link Form} component as well as many form control components.
27 */
28 public class FormTests extends App1TestCase
29 {
30
31 @Test
32 public void form_encoding_type()
33 {
34 openLinks("Form Encoding Type");
35
36 assertAttribute("//form/@enctype", "x-override");
37 }
38
39 @Test
40 public void page_context_in_form()
41 {
42 openLinks("Page Context in Form");
43
44 assertTextSeries("//div[@id='results']//li[%d]", 1, "betty", "wilma", "context with spaces", "context/with/slashes");
45 assertFieldValue("t:ac", "betty/wilma/context$0020with$0020spaces/context$002fwith$002fslashes");
46
47 clickAndWait(SUBMIT);
48
49 assertTextSeries("//div[@id='results']//li[%d]", 1, "betty", "wilma", "context with spaces", "context/with/slashes");
50 assertFieldValue("t:ac", "betty/wilma/context$0020with$0020spaces/context$002fwith$002fslashes");
51 }
52
53 @Test
54 public void password_field()
55 {
56 openLinks("PasswordFieldDemo");
57
58 type("userName", "howard");
59 type("password", "wrong-password");
60
61 clickAndWait(SUBMIT);
62
63 assertFieldValue("userName", "howard");
64 // Verify that password fields do not render a non-blank password, even
65 // when it is known.
66 assertFieldValue("password", "");
67
68 assertTextPresent("[howard]");
69 assertTextPresent("[wrong-password]");
70
71 type("password", "tapestry");
72
73 clickAndWait(SUBMIT);
74
75 assertTextPresent("You have provided the correct user name and password.");
76 }
77
78 @Test
79 public void server_side_validation_for_textfield_and_textarea() throws Exception
80 {
81 openLinks("ValidForm");
82
83 clickAndWait(SUBMIT);
84
85 assertTextPresent("You must provide a value for Email.");
86 // is an overridden validation error message:
87 assertTextPresent("Please provide a detailed description of the incident.");
88
89 type("email", "foo@bar.baz");
90 type("message", "Show me the money!");
91 type("hours", "foo");
92
93 clickAndWait(SUBMIT);
94
95 assertTextPresent("[false]");
96 assertTextPresent("You must provide an integer value for Hours.");
97
98 assertAttribute("//input[@id='hours']/@value", "foo");
99
100 type("hours", " 19 ");
101 click("//input[@id='urgent']");
102 clickAndWait(SUBMIT);
103
104 assertTextPresent("[foo@bar.baz]");
105 assertTextPresent("[Show me the money!]");
106 assertTextPresent("[true]");
107 assertTextPresent("[19]");
108 }
109
110 @Test
111 public void client_side_validation()
112 {
113 openLinks("Client Validation Demo");
114
115 clickAndWait("link=Reset Page State");
116
117 // Notice: click, not click and wait.
118
119 click(SUBMIT);
120
121 assertTextPresent("You must provide a value for First Name.");
122
123 type("firstName", "Howard");
124 type("lastName", "Lewis Ship");
125 type("birthYear", "1000");
126 type("password", "supersecret");
127
128 click(SUBMIT);
129
130 type("birthYear", "1966");
131 click("citizen");
132
133 clickAndWait(SUBMIT);
134
135 assertTextPresent("Howard", "Lewis Ship", "1966", "U.S. Citizen");
136 }
137
138 @Test
139 public void cancel_button()
140 {
141 openLinks("Client Validation Demo");
142
143 // Used to ensure that the <script> tag was present, but that's hard to
144 // do with script combining enabled.
145
146 clickAndWait("link=Clear Data");
147
148 clickAndWait("//input[@value='Cancel']");
149
150 assertText("message", "Form was cancelled.");
151 }
152
153 @Test
154 public void radio_group_validator()
155 {
156 openLinks("RadioDemo", "reset");
157
158 // Verify that the "required" validator works.
159 clickAndWait(SUBMIT);
160
161 assertTextPresent("You must provide a value for Department.");
162 }
163
164 // This test has been disabled because the use of the pattern attribute
165 // by the Regexp validator, prevents the form from submitting.
166 @Test(enabled=false)
167 public void regexp_validator()
168 {
169 openLinks("Regexp Demo");
170
171 String update = SUBMIT;
172
173 type("zipCode", "abc");
174
175 click(update); // but don't wait
176
177 assertTextPresent("A zip code consists of five or nine digits, eg: 02134 or 90125-4472.");
178
179 type("zipCode", "12345");
180
181 clickAndWait(update);
182
183 assertTextPresent("Zip code: [12345]");
184
185 type("zipCode", "12345-9876");
186
187 clickAndWait(update);
188
189 assertTextPresent("Zip code: [12345-9876]");
190 }
191
192 @Test
193 public void basic_datefield()
194 {
195 openLinks("DateField Demo", "Reset Page State", "english");
196
197 type("birthday", "24 dec 1966");
198 type("asteroidImpact", "05/28/2046");
199
200 clickAndWait(SUBMIT);
201
202 assertText("birthday-output", "12/24/1966");
203 assertText("impact-output", "05/28/2046");
204
205 assertFieldValue("birthday", "24 Dec 1966");
206 assertFieldValue("asteroidImpact", "5/28/2046");
207
208 clickAndWait("link=french");
209
210 click("css=.x-birthday .btn");
211
212 waitForAjaxRequestsToComplete();
213
214 assertText("//A[@class='topLabel']", "1966 d\u00e9cembre");
215 }
216
217 // TAP5-2197
218 @Test
219 public void datefield_leniency()
220 {
221 openLinks("DateField Demo", "Reset Page State", "english");
222
223 type("asteroidImpact", "00/00/0000");
224 type("lenient", "00/00/0000");
225
226 clickAndWait(SUBMIT);
227
228 // By default, DateField is not lenient anymore
229 assertText("css=div.x-impact p.help-block", "Date value '00/00/0000' is not parseable.");
230
231 // But this one is configured as such by setting the "lenient" parameter to true.
232 assertFalse(isElementPresent("css=div.x-lenient p.help-block"));
233
234 // Check whether a String coerced to a DateFormat results in a lenient or not instance
235 // according to the SymbolConstants.LENIENT_DATE_FORMAT symbol (default false)
236 assertText("coercedStringToDateFormatLenient", "false");
237
238 }
239
240 // TAP5-1057
241 @Test
242 public void xss_datefield()
243 {
244 openLinks("DateField Demo", "Reset Page State", "english");
245
246 type("asteroidImpact", "<script>alert('T5 is great'); </script>");
247
248 click("css=.x-impact .btn");
249
250 waitForAjaxRequestsToComplete();
251
252 assertSourcePresent("Unparseable date: \"&lt;script&gt;alert('T5 is great'); &lt;/script&gt;\"");
253 }
254
255 // TAP5-1409
256 @Test
257 public void datefield_select_newmonth_samedate()
258 {
259 openLinks("DateField Demo", "Reset Page State", "english");
260
261 //start with a known date...
262 type("asteroidImpact", "05/28/2035");
263
264 click("css=.x-impact .btn");
265
266 ExpectedCondition datePickerVisible = ExpectedConditions.visibilityOfElementLocated(By.cssSelector("div.datePicker"));
267
268 waitForCondition(datePickerVisible);
269 assertEquals(getText("css=td.selected"), "28");
270
271 //move to the next month.
272 click("css=button.nextButton");
273
274 //first, make sure that NOTHING shows as selected! The selected date is still 5/28/46
275
276 waitForSelectedToBeRemoved();
277
278
279 //make sure it's still selected if we navigate back...
280 click("css=button.previousButton");
281 waitForCSSSelectedElementToAppear("td.selected");
282
283 click("css=button.nextButton");
284
285 waitForSelectedToBeRemoved();
286
287 click("xpath=//td[text()='28']");
288 String pickerGoneSelector = "css=div.datePicker";
289 waitForInvisible(pickerGoneSelector);
290
291 assertFieldValue("asteroidImpact", "6/28/2035");
292
293 //a few other behaviors to check on as a side-effect of implementing the fix for 1409:
294 //1) If today is selected and it's the current month, pressing the "Today" button should close the popup
295 //2) If today is selected and we're on some other month, pressing the "Today" button should just take us
296 // back to the today.
297 //3) If today is not selected, pressing the "Today" button should set the date and close the popup.
298 //4) Pressing the "None" button should always close the popup and result in no date.
299
300 //#3
301 click("css=.x-impact .btn");
302
303 waitForCondition(datePickerVisible);
304 click("css=div.datePicker .footerTable button");
305 waitForInvisible(pickerGoneSelector);
306
307 String value = getValue("asteroidImpact");
308 assertFieldValue("asteroidImpact", new SimpleDateFormat("M/d/yyyy").format(new Date()));
309
310 //#2...
311 click("css=.x-impact .btn");
312
313 waitForCondition(datePickerVisible);
314 click("css=button.nextButton");
315
316 waitForSelectedToBeRemoved();
317
318 click("css=div.datePicker .footerTable button");
319 waitForCSSSelectedElementToAppear("td.selected");
320
321 //#1
322 click("css=div.datePicker .footerTable button");
323 waitForInvisible(pickerGoneSelector);
324 assertFieldValue("asteroidImpact", value);
325
326 //#4...
327
328 click("css=.x-impact .btn");
329
330 waitForCondition(datePickerVisible);
331
332 String noneButton = "//button[text()='None']";
333
334 click(noneButton);
335
336 waitForInvisible(pickerGoneSelector);
337
338 assertFieldValue("asteroidImpact", "");
339
340 click("css=.x-impact .btn");
341
342 waitForCondition(datePickerVisible);
343 assertFalse(isElementPresent("css=td.selected"));
344
345 click(noneButton);
346
347 waitForInvisible(pickerGoneSelector);
348 assertFieldValue("asteroidImpact", "");
349 }
350
351 private void waitForSelectedToBeRemoved()
352 {
353 waitForCondition("selenium.browserbot.getCurrentWindow().testSupport.findCSSMatchCount('td.selected') == 0", PAGE_LOAD_TIMEOUT);
354 }
355
356 // TAP5-1408, TAP5-2203
357 @Test
358 public void datefield_clickoutside_closes()
359 {
360 openLinks("DateField Demo", "Reset Page State", "english");
361
362 type("asteroidImpact", "05/28/2046");
363
364 click("css=.x-impact .btn");
365
366 ExpectedCondition datePickerVisible = ExpectedConditions.visibilityOfElementLocated(By.cssSelector("div.datePicker"));
367
368 waitForCondition(datePickerVisible);
369
370 click("css=.x-impact .btn");
371 waitForInvisible("css=div.datePicker");
372
373 //make sure that clicking somewhere outside the date picker
374 //closes it
375 click("css=.x-impact .btn");
376 waitForCondition(datePickerVisible);
377
378 click("css=h1");
379 waitForInvisible("css=div.datePicker");
380
381 //also make sure that clicking the month label /doesn't/ close the picker
382 click("css=.x-impact .btn");
383 waitForCondition(datePickerVisible);
384 click("css=a.topLabel");
385 waitForCSSSelectedElementToAppear("div.labelPopup");
386 click("css=div.labelPopup a");
387
388 waitForInvisible("css=div.labelPopup");
389 //It's basically impossible to express "wait until the popup doesn't disappear"
390 //Instead, we take advantage of knowing that the datepicker disappears with this bug /almost/
391 //immediately after picking the month label, so we sleep the test for a few seconds to provide
392 //ammple time for the bug to manifest.
393
394 waitForAjaxRequestsToComplete();
395
396 assertTrue(isVisible("css=div.datePicker"));
397 }
398
399 @Test
400 public void event_based_translate() throws Exception
401 {
402 openLinks("EventMethod Translator");
403
404 type("count", "123");
405 clickAndWait(SUBMIT);
406
407 assertTextPresent("Count: [123]");
408
409 type("count", "0");
410 clickAndWait(SUBMIT);
411
412 assertTextPresent("Count: [0]");
413
414 assertFieldValue("count", "zero");
415
416 type("count", "456");
417 clickAndWait(SUBMIT);
418
419 assertTextPresent("Count: [456]");
420
421 assertFieldValue("count", "456");
422
423 type("count", "ZERO");
424 clickAndWait(SUBMIT);
425
426 assertTextPresent("Count: [0]");
427
428 assertFieldValue("count", "zero");
429
430 // Try the server-side custom exception reporting.
431
432 type("count", "13");
433 clickAndWait(SUBMIT);
434
435 assertTextPresent("Event Handler Method Translate", "Thirteen is an unlucky number.");
436
437 type("count", "i");
438 clickAndWait(SUBMIT);
439
440 assertTextPresent("Event Handler Method Translate", "Rational numbers only, please.");
441 }
442
443 @Test
444 public void radio_button_and_group()
445 {
446 openLinks("RadioDemo");
447
448 String update = SUBMIT;
449
450 webDriver.findElements(By.cssSelector("label")).stream().filter(element-> element.getText().contains("Accounting")).findFirst().get().click();
451 clickAndWait(update);
452
453 assertTextPresent("Selected department: ACCOUNTING");
454
455 WebElement salesAndMarketing = webDriver.findElements(By.cssSelector("label")).stream().filter(element-> element.getText().contains("Sales And Marketin")).findFirst().get();
456 scrollIntoView(salesAndMarketing);
457 salesAndMarketing.click();
458
459 clickAndWait(update);
460
461 assertTextPresent("Selected department: SALES_AND_MARKETING");
462
463 // not in a loop ...
464 webDriver.findElements(By.cssSelector("label")).stream().filter(element-> element.getText().contains("Temp")).findFirst().get().click();
465
466 clickAndWait(update);
467
468 assertTextPresent("Selected position: TEMP");
469
470 webDriver.findElements(By.cssSelector("label")).stream().filter(element-> element.getText().contains("Lifer")).findFirst().get().click();
471
472 clickAndWait(update);
473
474 assertTextPresent("Selected position: LIFER");
475 }
476
477 @Test
478 public void disabled_fields() throws Exception
479 {
480 openLinks("Disabled Fields");
481
482 // The couple of places where there's a _0 suffix is related to
483 // the fix for https://issues.apache.org/jira/browse/TAP5-1632
484 String[] paths = new String[]
485 {"//input[@id='textfield']",
486
487 "//input[@id='passwordfield']",
488
489 "//textarea[@id='textarea']",
490
491 "//input[@id='checkbox']",
492
493 "//select[@id='select_0']",
494
495 "//input[@id='radio1']",
496
497 "//input[@id='radio2']",
498
499 "//input[@id='datefield']",
500
501 "//div[@class='palette']//input[@type='hidden']",
502
503 "//div[@class='palette-available']//select",
504
505 "//div[@class='palette-selected']//select",
506
507 "//input[@name='checklist']",
508
509 // TAP5-2078
510 "//input[@name='radiogroup']",
511
512 "//input[@id='submit_0']"};
513
514 for (String path : paths)
515 {
516 String locator = String.format("%s/@disabled", path);
517
518 assertAttribute(locator, "disabled");
519 }
520
521 assertAttribute("css=div.palette .btn@disabled", "true");
522
523 //TAP5-2078
524 clickAndWait("//input[@value='Continue']");
525
526 assertFalse(isTextPresent("This should not happen"));
527 }
528
529 /**
530 * TAPESTRY-2056
531 */
532 @Test
533 public void null_field_strategy()
534 {
535 openLinks("Null Field Strategy Demo");
536
537 String locator = "//span[@id='value']";
538
539 assertText(locator, "");
540
541 assertAttribute("//input[@id='number']/@value", "0");
542
543 type("number", "");
544
545 clickAndWait(SUBMIT);
546
547 assertText(locator, "0");
548 }
549
550 /**
551 * TAPESTRY-1647
552 */
553 @Test
554 public void label_invokes_validation_decorator_at_correct_time()
555 {
556 openLinks("Override Validation Decorator");
557
558 // This is sub-optimal, as it doesn't esnure that the before/after field
559 // values really do wrap around
560 // the field (they do, but that's hard to prove!). It is also susceptible to
561 // idiosyncrasies around how Tapestry renders attributes, and how the browser
562 // represents them.
563
564 // Along the way we are also testing:
565 // - primitive types are automatically required
566 // - AbstractTextField.isRequired() and the logic inside
567 // ComponentFieldValidator.isRequired()
568
569 assertSourcePresent(
570 "[Before label for Value]<label for=\"value\" class=\"control-label\">Value</label>[After label for Value]",
571 "[Before field Value]",
572 "[After field Value (optional)]",
573 "[Before label for Required Value]<label for=\"requiredValue\" class=\"control-label\">Required Value</label>[After label for Required Value]",
574 "[Before field Required Value]", "[After field Required Value (required)]");
575 }
576
577 /**
578 * TAPESTRY-2085
579 */
580 @Test
581 public void wrapper_types_with_text_field()
582 {
583 openLinks("TextField Wrapper Types", "Reset Page State");
584
585 assertFieldValue("count", "");
586 assertText("value", "null");
587
588 type("count", "0");
589 clickAndWait(SUBMIT);
590
591 assertFieldValue("count", "0");
592 assertText("value", "0");
593
594 type("count", "1");
595 clickAndWait(SUBMIT);
596
597 assertFieldValue("count", "1");
598 assertText("value", "1");
599
600 clickAndWait("link=clear");
601
602 assertFieldValue("count", "");
603 assertText("value", "null");
604 }
605
606 @Test
607 public void submit_with_context()
608 {
609 openLinks("Submit With Context");
610
611 clickAndWait(SUBMIT);
612
613 assertTextPresent("Result: 10.14159");
614 }
615
616 /**
617 * TAPESTRY-2563
618 */
619 @Test
620 public void form_action_via_get()
621 {
622 open(getBaseURL() + "validform.form", "true");
623
624 assertTextPresent("Forms require that the request method be POST and that the t:formdata query parameter have values.");
625 }
626
627 /**
628 * TAPESTRY-2352
629 */
630 @Test
631 public void client_field_format_validation()
632 {
633 openLinks("Client Format Validation");
634
635 type("amount", "abc");
636 type("quantity", "abc");
637
638 click(SUBMIT);
639
640 assertTextPresent("You must provide a numeric value for Amount.",
641 "Provide quantity as a number.");
642 }
643
644 /**
645 * TAPESTRY-2438
646 */
647 @Test
648 public void validation_exception_thrown_from_validate_form_event_handler()
649 {
650 openLinks("ValidationForm ValidationException Demo");
651
652 clickAndWait(SUBMIT);
653
654 assertTextPresent("From event handler method.");
655
656 assertText("event", "failure");
657 }
658
659 @Test
660 public void form_field_outside_form()
661 {
662 openLinks("Form Field Outside Form");
663
664 assertTextPresent(
665 "org.apache.tapestry5.internal.services.RenderQueueException",
666 "Render queue error in SetupRender[FormFieldOutsideForm:textfield]: Component FormFieldOutsideForm:textfield must be enclosed by a Form component.",
667 "context:FormFieldOutsideForm.tml, line 5");
668 }
669
670 /**
671 * TAP5-281
672 */
673 @Test
674 public void nested_form_check()
675 {
676 openLinks("Nested Form Demo");
677
678 assertTextPresent("Form components may not be placed inside other Form components.");
679 }
680
681 /**
682 * TAP5-87
683 */
684 @Test
685 public void blank_password_does_not_update()
686 {
687 openLinks("Blank Password Demo");
688
689 type("password", "secret");
690
691 clickAndWait(SUBMIT);
692
693 assertFieldValue("password", "");
694
695 assertText("visiblepassword", "secret");
696
697 clickAndWait(SUBMIT);
698
699 assertFieldValue("password", "");
700
701 assertText("visiblepassword", "secret");
702 }
703
704 /**
705 * TAP5-228: And to think I almost blew off the integration tests!
706 */
707 @Test
708 public void per_form_validation_messages_and_constraints()
709 {
710 openLinks("Per-Form Validation Messages");
711
712 clickAndWait("//input[@type='submit' and @value='Login']");
713
714 assertTextPresent("Enter the unique user id you provided when you registerred.");
715
716 type("userId", "aaa");
717
718 clickAndWait("//input[@type='submit' and @value='Login']");
719
720 assertTextPresent("You must provide at least 10 characters for User Id.");
721
722 clickAndWait("//input[@type='submit' and @value='Register']");
723
724 assertTextPresent("Enter a unique user id, such as your initials.");
725
726 type("userId_0", "aaa");
727
728 clickAndWait("//input[@type='submit' and @value='Register']");
729
730 assertTextPresent("You must provide at least 20 characters for User Id.");
731 }
732
733 /**
734 * TAP5-719
735 */
736 @Test
737 public void link_submit_without_validator()
738 {
739 openLinks("LinkSubmit Without Validator Demo");
740
741 type("searchField", "Anders Haraldsson");
742
743 clickAndWait("//a[@id='searchLink']");
744
745 assertTextPresent("Result: Anders Haraldsson not found!");
746 }
747
748 /**
749 * TAP5-211
750 */
751 @Test
752 public void client_side_numeric_validation()
753 {
754 openLinks("Client-Side Numeric Validation", "Reset Page State", "Setup Values");
755
756 assertText("outputLongValue", "1000");
757 assertText("outputDoubleValue", "1234.67");
758
759 assertFieldValue("longValue", "1000");
760 assertFieldValue("doubleValue", "1,234.67");
761
762 type("longValue", "2,000 ");
763 type("doubleValue", " -456,789.12");
764
765 clickAndWait(SUBMIT);
766
767 assertText("outputLongValue", "2000");
768 assertText("outputDoubleValue", "-456789.12");
769
770 assertFieldValue("longValue", "2000");
771 assertFieldValue("doubleValue", "-456,789.12");
772
773 clickAndWait("link=Switch to German");
774
775 assertText("outputLongValue", "2000");
776 assertText("outputDoubleValue", "-456789.12");
777
778 assertFieldValue("longValue", "2000");
779 assertFieldValue("doubleValue", "-456.789,12");
780
781 type("longValue", "3.000");
782 type("doubleValue", "5.444.333,22");
783
784 clickAndWait(SUBMIT);
785
786 assertFieldValue("longValue", "3000");
787 assertFieldValue("doubleValue", "5.444.333,22");
788
789 assertText("outputLongValue", "3000");
790 assertText("outputDoubleValue", "5444333.22");
791
792 clickAndWait("link=Setup Values");
793
794 type("longValue", "4000.");
795 click(SUBMIT);
796
797 assertTextPresent("You must provide an integer value for Long Value.");
798
799 type("doubleValue", "abc");
800
801 click(SUBMIT);
802
803 assertTextPresent("You must provide a numeric value for Double Value.");
804 }
805
806 @Test
807 public void client_validation_for_numeric_fields_that_are_not_required()
808 {
809 openLinks("Form Zone Demo");
810
811 type("longValue", "alpha");
812
813 click(SUBMIT);
814
815 assertTextPresent("You must provide an integer value for Long Value.");
816
817 type("longValue", "37");
818
819 click(SUBMIT);
820
821 waitForElementToAppear("outputvalue");
822
823 assertText("outputvalue", "37");
824 }
825
826 @Test
827 public void hidden_field()
828 {
829 openLinks("Hidden Demo", "setup");
830
831 clickAndWait(SUBMIT);
832
833 assertText("stored", "12345");
834 }
835
836 @Test
837 public void validation_constraints_from_messages()
838 {
839 openLinks("Validation Constraints From Messages");
840
841 click(SUBMIT);
842
843 assertTextPresent("You must provide a value for Name.");
844 assertTextPresent("You must provide a value for Age.");
845
846 type("name", "behemoth");
847 type("age", "0");
848 select("type", "label=Snake");
849
850 click(SUBMIT);
851 assertTextPresent("Age requires a value of at least 1.");
852
853 type("age", "121");
854 click(SUBMIT);
855 assertTextPresent("Age requires a value no larger than 120.");
856
857 type("age", "5");
858 clickAndWait(SUBMIT);
859 }
860
861 /**
862 * TAP5-157
863 */
864 @Test
865 public void link_submit_component()
866 {
867 openLinks("LinkSubmit Demo");
868
869 click("//a[@id='fred']");
870
871 assertTextPresent("You must provide a value for Name.");
872
873 type("name", "Wilma");
874
875 clickAndWait("link=Fred");
876
877 assertText("name-value", "Wilma");
878 assertText("last-clicked", "Fred");
879 assertTextPresent("Result: 10.14159");
880
881 type("name", "Betty");
882
883 clickAndWait("link=Barney");
884
885 assertText("name-value", "Betty");
886 assertText("last-clicked", "Barney");
887 }
888
889 /**
890 * TAP5-2183
891 */
892 @Test
893 public void link_submit_component_with_nested_element()
894 {
895 openLinks("LinkSubmit Demo");
896
897 type("name", "Wilma");
898
899 clickAndWait("css=.glyphicon-star");
900
901 assertText("name-value", "Wilma");
902 assertText("last-clicked", "Pebbles");
903 }
904
905 @Test
906 public void calendar_field_inside_bean_editor()
907 {
908 openLinks("BeanEditor / Calendar Demo", "Reset Page State");
909
910 type("calendar", "04/06/1978");
911
912 clickAndWait(SUBMIT);
913
914 assertTextPresent("Apr 6, 1978");
915
916 // TAP5-1043
917 clickAndWait("link=clear");
918 }
919
920 @Test
921 public void image_submit_triggers_selected_event()
922 {
923 openLinks("Submit with an Image Demo");
924
925 type("value", "barney gumble");
926
927 clickAndWait("//input[@type='image']");
928
929 assertText("outputvalue", "barney gumble");
930
931 assertText("eventfired", "true");
932 }
933
934 /**
935 * Tests for forms and form submissions and basic form control components.
936 * also tests a few other things, such as
937 * computed default bindings and invisible instrumentation.
938 */
939 @Test
940 public void simple_form()
941 {
942 openLinks("SimpleForm");
943
944 assertText("//label[@for='disabled']", "Disabled");
945
946 // This demonstrates TAPESTRY-1642:
947 assertText("//label[@for='email']", "User Email");
948
949 assertText("//label[@for='message']", "Incident Message");
950 assertText("//label[@for='operatingSystem']", "Operating System");
951 assertText("//label[@for='department']", "Department");
952 assertText("//label[@for='urgent']", "Urgent Processing Requested");
953
954 assertFieldValue("email", "");
955 assertFieldValue("message", "");
956 assertFieldValue("operatingSystem", "osx");
957 assertFieldValue("department", "");
958 assertFieldValue("urgent", "on");
959
960 clickAndWait(SUBMIT);
961
962 assertTextPresent("department: []");
963
964 type("email", "foo@bar.baz");
965 type("message", "Message for you, sir!");
966 select("operatingSystem", "Windows NT");
967 select("department", "R&D");
968 click("urgent");
969
970 clickAndWait(SUBMIT);
971
972 assertFieldValue("email", "foo@bar.baz");
973 assertFieldValue("message", "Message for you, sir!");
974 assertFieldValue("urgent", "off");
975
976 // Tried to use "email:" and "exact:email:" but Selenium 0.8.1 doesn't
977 // seem to accept that.
978
979 assertTextPresent("[foo@bar.baz]", "[Message for you, sir!]", "[false]", "[winnt]", "[RESEARCH_AND_DESIGN]");
980
981 // Haven't figured out how to get selenium to check that fields are
982 // disabled.
983 }
984
985 /**
986 * TAP5-915
987 */
988 @Test
989 public void override_datefield_message_catalog()
990 {
991 open(getBaseURL() + "overridedatefieldmessagecatalogdemo");
992
993 type("birthday", "aaaaa");
994
995 clickAndWait("//input[@type='submit' and @value='Go']");
996
997 assertTextPresent("The input 'aaaaa' is not a valid date");
998 }
999
1000 /**
1001 * TAP5-52.
1002 */
1003 @Test
1004 public void single_error_message()
1005 {
1006 open(getBaseURL() + "singleerrordemo");
1007
1008 clickAndWait(SUBMIT);
1009
1010 assertTextPresent("You must provide a value for Username");
1011 assertTextPresent("You must provide a value for Password");
1012
1013 type("username", "Igor");
1014
1015 clickAndWait(SUBMIT);
1016
1017 assertFalse(isTextPresent("You must provide a value for Username"));
1018 assertTextPresent("You must provide a value for Password");
1019
1020 type("password", "secret");
1021
1022 clickAndWait(SUBMIT);
1023
1024 assertFalse(isTextPresent("You must provide a value for Username"));
1025 assertFalse(isTextPresent("You must provide a value for Password"));
1026 }
1027
1028 /**
1029 * TAP5-1024
1030 */
1031 @Test
1032 public void use_of_cancel_mode_on_submit_button()
1033 {
1034 openLinks("Cancel Demo");
1035
1036 clickAndWait("//input[@value='Cancel Form']");
1037
1038 assertText("message", "Form was canceled.");
1039 }
1040
1041 @Test
1042 public void use_of_cancel_mode_with_submitlink()
1043 {
1044 openLinks("Cancel Demo");
1045
1046 clickAndWait("link=Cancel Form");
1047
1048 assertText("message", "Form was canceled.");
1049 }
1050
1051 @Test
1052 public void validation_decoration_for_select() throws Exception
1053 {
1054 openLinks("Select Demo");
1055
1056 clickAndWait(SUBMIT);
1057
1058 assertTextPresent("You must provide a value for Color.");
1059
1060 select("color", "label=Green");
1061
1062 clickAndWait(SUBMIT);
1063
1064 assertTextPresent("Selected color: Green");
1065 }
1066
1067 /**
1068 * TAP5-1098.
1069 */
1070 @Test
1071 public void create_select_model_from_objects_and_property_name() throws Exception
1072 {
1073 openLinks("SelectModel from objects and property name");
1074
1075 select("track", "label=The Calling");
1076
1077 clickAndWait(SUBMIT);
1078
1079 assertTextPresent("Selected track: The Calling, Synaesthetic");
1080 }
1081
1082 @Test
1083 public void create_select_model_from_objects() throws Exception
1084 {
1085 openLinks("SelectModel from objects");
1086
1087 select("track", "label=The Calling");
1088
1089 clickAndWait(SUBMIT);
1090
1091 assertTextPresent("Selected track: The Calling, Synaesthetic");
1092 }
1093
1094 @Test
1095 public void create_select_model_coercion() throws Exception
1096 {
1097 openLinks("SelectModel coercion");
1098
1099 select("track", "label=The Calling");
1100
1101 clickAndWait(SUBMIT);
1102
1103 assertTextPresent("Selected track: The Calling, Synaesthetic");
1104 }
1105
1106 @Test
1107 public void validation_macro() throws Exception
1108 {
1109 openLinks("Validator Macro Demo");
1110
1111 clickAndWait(SUBMIT);
1112
1113 assertTextPresent("You must provide a value for Password.");
1114 assertTextPresent("You must provide a value for Password2.");
1115
1116 type("password", "abcdefg");
1117 type("password2", "x");
1118
1119 clickAndWait(SUBMIT);
1120
1121 assertTextPresent("You may provide at most 3 characters for Password.");
1122 assertTextPresent("You must provide at least 2 characters for Password2.");
1123
1124 type("password", "a");
1125 type("password2", "wxyz");
1126
1127 clickAndWait(SUBMIT);
1128
1129 assertTextPresent("You must provide at least 2 characters for Password.");
1130 assertTextPresent("You may provide at most 3 characters for Password2.");
1131
1132 type("password", "ab");
1133 type("password2", "xyz");
1134
1135 clickAndWait(SUBMIT);
1136
1137 assertTextPresent("Password: ab");
1138 assertTextPresent("Password2: xyz");
1139 }
1140
1141 @Test
1142 public void checklist_select() throws Exception
1143 {
1144 openLinks("Checklist Demo");
1145
1146 clickAndWait(SUBMIT);
1147 assertTextPresent("You must provide a value for Color.");
1148
1149 check("//input[@value='Green']");
1150
1151 clickAndWait(SUBMIT);
1152
1153 assertTextPresent("Selected colors: [Green]");
1154
1155 check("//input[@value='Red']");
1156
1157 clickAndWait(SUBMIT);
1158
1159 assertTextPresent("Selected colors: [Green, Red]");
1160
1161 check("//input[@value='Blue']");
1162 uncheck("//input[@value='Green']");
1163
1164 clickAndWait(SUBMIT);
1165
1166 assertTextPresent("Selected colors: [Blue, Red]");
1167 }
1168
1169 @Test
1170 public void checkFormLinkParameters() throws Exception
1171 {
1172 openLinks("FormLinkParameters Demo");
1173 assertAttribute("//input[@name='myparam']/@value", "!@#$%^&*()_+=");
1174
1175 clickAndWait("link=SetValue");
1176 assertTextPresent("Result = '!@#$%^&*()_+='");
1177
1178 clickAndWait(SUBMIT);
1179 assertTextPresent("Result = '!@#$%^&*()_+='");
1180 }
1181
1182 /**
1183 * TAP5-2223.
1184 */
1185 @Test
1186 public void optionGroup_form()
1187 {
1188 openLinks("OptionGroupForm Demo");
1189
1190 assertTextPresent("entity.id: [1]");
1191
1192 select("entity", "label2");
1193
1194 clickAndWait(SUBMIT);
1195
1196 assertTextPresent("entity.id: [2]");
1197 }
1198
1199 /** TAP5-2331 */
1200 @Test
1201 public void form_fields_client_id_parameter()
1202 {
1203 final String[] clientIds = {"clientId-0", "clientId-1"};
1204
1205 openLinks("Form Field clientId Parameter Demo");
1206
1207 for (int i = 0; i < 4; i++) {
1208
1209 for (String clientId : clientIds)
1210 {
1211 assertTrue(selenium.isElementPresent(clientId));
1212 }
1213
1214 click("updateZone");
1215 waitForAjaxRequestsToComplete();
1216
1217 }
1218
1219 }
1220
1221 /** TAP5-2301 */
1222 @Test
1223 public void select_context() {
1224
1225 openLinks("MultiZone Update inside a Form");
1226 selenium.select("selectValue1", "label=3 pre ajax");
1227 waitForAjaxRequestsToComplete();
1228 assertEquals(
1229 "4 post ajax, number 013, retention policy RUNTIME",
1230 selenium.getText("//select[@id='selectValue2']/option"));
1231
1232 }
1233
1234 /** TAP5-1815. In this webapp, HTML5 support is disabled, so we check whether it actually is disabled */
1235 @Test
1236 public void html5_support_disabled() throws Exception
1237 {
1238 openLinks("ValidForm");
1239 assertEquals("text", getAttribute("emailValidator@type")); // if HTML5 support was enabled, this would be "email"
1240 }
1241
1242 /** TAP5-736 **/
1243 @Test
1244 public void textfield_requires_non_null_validate_parameter() throws Exception
1245 {
1246 openLinks("TextField with null validate parameter");
1247 if(isTextPresent("java.lang.NullPointerException")){
1248 reportAndThrowAssertionError("Unexpected NullPointerException was thrown");
1249 }
1250 assertTextPresent("This parameter is not allowed to be null.");
1251 }
1252
1253 /** TAP5-2467 **/
1254 @Test
1255 public void validate_in_error_event() {
1256 openLinks("Validate in error Event");
1257
1258 click(SUBMIT);
1259
1260 waitForElementToAppear("validate-in-error");
1261
1262 assertTextPresent("Validate in error");
1263 }
1264
1265 // TAP5-2204
1266 @Test
1267 public void select_model_with_auto_security_and_non_persistent_model() throws Exception
1268 {
1269 openLinks("Select Demo");
1270
1271 select("month", "label=August");
1272
1273 clickAndWait(SUBMIT);
1274
1275 assertTextPresent("Selected month: August");
1276 }
1277 }