| // 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 org.apache.tapestry5.integration.app1; |
| |
| import java.text.SimpleDateFormat; |
| import java.util.Date; |
| |
| import org.apache.tapestry5.corelib.components.Form; |
| import org.openqa.selenium.By; |
| import org.openqa.selenium.WebElement; |
| import org.openqa.selenium.support.ui.ExpectedCondition; |
| import org.openqa.selenium.support.ui.ExpectedConditions; |
| import org.testng.annotations.Test; |
| |
| /** |
| * Tests for the {@link Form} component as well as many form control components. |
| */ |
| public class FormTests extends App1TestCase |
| { |
| |
| @Test |
| public void form_encoding_type() |
| { |
| openLinks("Form Encoding Type"); |
| |
| assertAttribute("//form/@enctype", "x-override"); |
| } |
| |
| @Test |
| public void page_context_in_form() |
| { |
| openLinks("Page Context in Form"); |
| |
| assertTextSeries("//div[@id='results']//li[%d]", 1, "betty", "wilma", "context with spaces", "context/with/slashes"); |
| assertFieldValue("t:ac", "betty/wilma/context$0020with$0020spaces/context$002fwith$002fslashes"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextSeries("//div[@id='results']//li[%d]", 1, "betty", "wilma", "context with spaces", "context/with/slashes"); |
| assertFieldValue("t:ac", "betty/wilma/context$0020with$0020spaces/context$002fwith$002fslashes"); |
| } |
| |
| @Test |
| public void password_field() |
| { |
| openLinks("PasswordFieldDemo"); |
| |
| type("userName", "howard"); |
| type("password", "wrong-password"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertFieldValue("userName", "howard"); |
| // Verify that password fields do not render a non-blank password, even |
| // when it is known. |
| assertFieldValue("password", ""); |
| |
| assertTextPresent("[howard]"); |
| assertTextPresent("[wrong-password]"); |
| |
| type("password", "tapestry"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("You have provided the correct user name and password."); |
| } |
| |
| @Test |
| public void server_side_validation_for_textfield_and_textarea() throws Exception |
| { |
| openLinks("ValidForm"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("You must provide a value for Email."); |
| // is an overridden validation error message: |
| assertTextPresent("Please provide a detailed description of the incident."); |
| |
| type("email", "foo@bar.baz"); |
| type("message", "Show me the money!"); |
| type("hours", "foo"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("[false]"); |
| assertTextPresent("You must provide an integer value for Hours."); |
| |
| assertAttribute("//input[@id='hours']/@value", "foo"); |
| |
| type("hours", " 19 "); |
| click("//input[@id='urgent']"); |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("[foo@bar.baz]"); |
| assertTextPresent("[Show me the money!]"); |
| assertTextPresent("[true]"); |
| assertTextPresent("[19]"); |
| } |
| |
| @Test |
| public void client_side_validation() |
| { |
| openLinks("Client Validation Demo"); |
| |
| clickAndWait("link=Reset Page State"); |
| |
| // Notice: click, not click and wait. |
| |
| click(SUBMIT); |
| |
| assertTextPresent("You must provide a value for First Name."); |
| |
| type("firstName", "Howard"); |
| type("lastName", "Lewis Ship"); |
| type("birthYear", "1000"); |
| type("password", "supersecret"); |
| |
| click(SUBMIT); |
| |
| type("birthYear", "1966"); |
| click("citizen"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("Howard", "Lewis Ship", "1966", "U.S. Citizen"); |
| } |
| |
| @Test |
| public void cancel_button() |
| { |
| openLinks("Client Validation Demo"); |
| |
| // Used to ensure that the <script> tag was present, but that's hard to |
| // do with script combining enabled. |
| |
| clickAndWait("link=Clear Data"); |
| |
| clickAndWait("//input[@value='Cancel']"); |
| |
| assertText("message", "Form was cancelled."); |
| } |
| |
| @Test |
| public void radio_group_validator() |
| { |
| openLinks("RadioDemo", "reset"); |
| |
| // Verify that the "required" validator works. |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("You must provide a value for Department."); |
| } |
| |
| // This test has been disabled because the use of the pattern attribute |
| // by the Regexp validator, prevents the form from submitting. |
| @Test(enabled=false) |
| public void regexp_validator() |
| { |
| openLinks("Regexp Demo"); |
| |
| String update = SUBMIT; |
| |
| type("zipCode", "abc"); |
| |
| click(update); // but don't wait |
| |
| assertTextPresent("A zip code consists of five or nine digits, eg: 02134 or 90125-4472."); |
| |
| type("zipCode", "12345"); |
| |
| clickAndWait(update); |
| |
| assertTextPresent("Zip code: [12345]"); |
| |
| type("zipCode", "12345-9876"); |
| |
| clickAndWait(update); |
| |
| assertTextPresent("Zip code: [12345-9876]"); |
| } |
| |
| @Test |
| public void basic_datefield() |
| { |
| openLinks("DateField Demo", "Reset Page State", "english"); |
| |
| type("birthday", "24 dec 1966"); |
| type("asteroidImpact", "05/28/2046"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertText("birthday-output", "12/24/1966"); |
| assertText("impact-output", "05/28/2046"); |
| |
| assertFieldValue("birthday", "24 Dec 1966"); |
| assertFieldValue("asteroidImpact", "5/28/2046"); |
| |
| clickAndWait("link=french"); |
| |
| click("css=.x-birthday .btn"); |
| |
| waitForAjaxRequestsToComplete(); |
| |
| assertText("//A[@class='topLabel']", "1966 d\u00e9cembre"); |
| } |
| |
| // TAP5-2197 |
| @Test |
| public void datefield_leniency() |
| { |
| openLinks("DateField Demo", "Reset Page State", "english"); |
| |
| type("asteroidImpact", "00/00/0000"); |
| type("lenient", "00/00/0000"); |
| |
| clickAndWait(SUBMIT); |
| |
| // By default, DateField is not lenient anymore |
| assertText("css=div.x-impact p.help-block", "Date value '00/00/0000' is not parseable."); |
| |
| // But this one is configured as such by setting the "lenient" parameter to true. |
| assertFalse(isElementPresent("css=div.x-lenient p.help-block")); |
| |
| // Check whether a String coerced to a DateFormat results in a lenient or not instance |
| // according to the SymbolConstants.LENIENT_DATE_FORMAT symbol (default false) |
| assertText("coercedStringToDateFormatLenient", "false"); |
| |
| } |
| |
| // TAP5-1057 |
| @Test |
| public void xss_datefield() |
| { |
| openLinks("DateField Demo", "Reset Page State", "english"); |
| |
| type("asteroidImpact", "<script>alert('T5 is great'); </script>"); |
| |
| click("css=.x-impact .btn"); |
| |
| waitForAjaxRequestsToComplete(); |
| |
| assertSourcePresent("Unparseable date: \"<script>alert('T5 is great'); </script>\""); |
| } |
| |
| // TAP5-1409 |
| @Test |
| public void datefield_select_newmonth_samedate() |
| { |
| openLinks("DateField Demo", "Reset Page State", "english"); |
| |
| //start with a known date... |
| type("asteroidImpact", "05/28/2035"); |
| |
| click("css=.x-impact .btn"); |
| |
| ExpectedCondition datePickerVisible = ExpectedConditions.visibilityOfElementLocated(By.cssSelector("div.datePicker")); |
| |
| waitForCondition(datePickerVisible); |
| assertEquals(getText("css=td.selected"), "28"); |
| |
| //move to the next month. |
| click("css=button.nextButton"); |
| |
| //first, make sure that NOTHING shows as selected! The selected date is still 5/28/46 |
| |
| waitForSelectedToBeRemoved(); |
| |
| |
| //make sure it's still selected if we navigate back... |
| click("css=button.previousButton"); |
| waitForCssSelectorToAppear("td.selected"); |
| |
| click("css=button.nextButton"); |
| |
| waitForSelectedToBeRemoved(); |
| |
| click("xpath=//td[text()='28']"); |
| String pickerGoneSelector = "css=div.datePicker"; |
| waitForInvisible(pickerGoneSelector); |
| |
| assertFieldValue("asteroidImpact", "6/28/2035"); |
| |
| //a few other behaviors to check on as a side-effect of implementing the fix for 1409: |
| //1) If today is selected and it's the current month, pressing the "Today" button should close the popup |
| //2) If today is selected and we're on some other month, pressing the "Today" button should just take us |
| // back to the today. |
| //3) If today is not selected, pressing the "Today" button should set the date and close the popup. |
| //4) Pressing the "None" button should always close the popup and result in no date. |
| |
| //#3 |
| click("css=.x-impact .btn"); |
| |
| waitForCondition(datePickerVisible); |
| click("css=div.datePicker .footerTable button"); |
| waitForInvisible(pickerGoneSelector); |
| |
| String value = getValue("asteroidImpact"); |
| assertFieldValue("asteroidImpact", new SimpleDateFormat("M/d/yyyy").format(new Date())); |
| |
| //#2... |
| click("css=.x-impact .btn"); |
| |
| waitForCondition(datePickerVisible); |
| click("css=button.nextButton"); |
| |
| waitForSelectedToBeRemoved(); |
| |
| click("css=div.datePicker .footerTable button"); |
| waitForCssSelectorToAppear("td.selected"); |
| |
| //#1 |
| click("css=div.datePicker .footerTable button"); |
| waitForInvisible(pickerGoneSelector); |
| assertFieldValue("asteroidImpact", value); |
| |
| //#4... |
| |
| click("css=.x-impact .btn"); |
| |
| waitForCondition(datePickerVisible); |
| |
| String noneButton = "//button[text()='None']"; |
| |
| click(noneButton); |
| |
| waitForInvisible(pickerGoneSelector); |
| |
| assertFieldValue("asteroidImpact", ""); |
| |
| click("css=.x-impact .btn"); |
| |
| waitForCondition(datePickerVisible); |
| assertFalse(isElementPresent("css=td.selected")); |
| |
| click(noneButton); |
| |
| waitForInvisible(pickerGoneSelector); |
| assertFieldValue("asteroidImpact", ""); |
| } |
| |
| private void waitForSelectedToBeRemoved() |
| { |
| waitForCondition("selenium.browserbot.getCurrentWindow().testSupport.findCSSMatchCount('td.selected') == 0", PAGE_LOAD_TIMEOUT); |
| } |
| |
| // TAP5-1408, TAP5-2203 |
| @Test |
| public void datefield_clickoutside_closes() |
| { |
| openLinks("DateField Demo", "Reset Page State", "english"); |
| |
| type("asteroidImpact", "05/28/2046"); |
| |
| click("css=.x-impact .btn"); |
| |
| ExpectedCondition datePickerVisible = ExpectedConditions.visibilityOfElementLocated(By.cssSelector("div.datePicker")); |
| |
| waitForCondition(datePickerVisible); |
| |
| click("css=.x-impact .btn"); |
| waitForInvisible("css=div.datePicker"); |
| |
| //make sure that clicking somewhere outside the date picker |
| //closes it |
| click("css=.x-impact .btn"); |
| waitForCondition(datePickerVisible); |
| |
| click("css=h1"); |
| waitForInvisible("css=div.datePicker"); |
| |
| //also make sure that clicking the month label /doesn't/ close the picker |
| click("css=.x-impact .btn"); |
| waitForCondition(datePickerVisible); |
| click("css=a.topLabel"); |
| waitForCssSelectorToAppear("div.labelPopup"); |
| click("css=div.labelPopup a"); |
| |
| waitForInvisible("css=div.labelPopup"); |
| //It's basically impossible to express "wait until the popup doesn't disappear" |
| //Instead, we take advantage of knowing that the datepicker disappears with this bug /almost/ |
| //immediately after picking the month label, so we sleep the test for a few seconds to provide |
| //ammple time for the bug to manifest. |
| |
| waitForAjaxRequestsToComplete(); |
| |
| assertTrue(isVisible("css=div.datePicker")); |
| } |
| |
| @Test |
| public void event_based_translate() throws Exception |
| { |
| openLinks("EventMethod Translator"); |
| |
| type("count", "123"); |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("Count: [123]"); |
| |
| type("count", "0"); |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("Count: [0]"); |
| |
| assertFieldValue("count", "zero"); |
| |
| type("count", "456"); |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("Count: [456]"); |
| |
| assertFieldValue("count", "456"); |
| |
| type("count", "ZERO"); |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("Count: [0]"); |
| |
| assertFieldValue("count", "zero"); |
| |
| // Try the server-side custom exception reporting. |
| |
| type("count", "13"); |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("Event Handler Method Translate", "Thirteen is an unlucky number."); |
| |
| type("count", "i"); |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("Event Handler Method Translate", "Rational numbers only, please."); |
| } |
| |
| @Test |
| public void radio_button_and_group() |
| { |
| openLinks("RadioDemo"); |
| |
| String update = SUBMIT; |
| |
| webDriver.findElements(By.cssSelector("label")).stream().filter(element-> element.getText().contains("Accounting")).findFirst().get().click(); |
| clickAndWait(update); |
| |
| assertTextPresent("Selected department: ACCOUNTING"); |
| |
| WebElement salesAndMarketing = webDriver.findElements(By.cssSelector("label")).stream().filter(element-> element.getText().contains("Sales And Marketin")).findFirst().get(); |
| scrollIntoView(salesAndMarketing); |
| salesAndMarketing.click(); |
| |
| clickAndWait(update); |
| |
| assertTextPresent("Selected department: SALES_AND_MARKETING"); |
| |
| // not in a loop ... |
| WebElement temp = webDriver.findElements(By.cssSelector("label")).stream().filter(element-> element.getText().contains("Temp")).findFirst().get(); |
| scrollIntoView(temp); |
| temp.click(); |
| |
| clickAndWait(update); |
| |
| assertTextPresent("Selected position: TEMP"); |
| |
| WebElement lifer = webDriver.findElements(By.cssSelector("label")).stream().filter(element-> element.getText().contains("Lifer")).findFirst().get(); |
| scrollIntoView(lifer); |
| lifer.click(); |
| |
| clickAndWait(update); |
| |
| assertTextPresent("Selected position: LIFER"); |
| } |
| |
| @Test |
| public void disabled_fields() throws Exception |
| { |
| openLinks("Disabled Fields"); |
| |
| // The couple of places where there's a _0 suffix is related to |
| // the fix for https://issues.apache.org/jira/browse/TAP5-1632 |
| String[] paths = new String[] |
| {"//input[@id='textfield']", |
| |
| "//input[@id='passwordfield']", |
| |
| "//textarea[@id='textarea']", |
| |
| "//input[@id='checkbox']", |
| |
| "//select[@id='select_0']", |
| |
| "//input[@id='radio1']", |
| |
| "//input[@id='radio2']", |
| |
| "//input[@id='datefield']", |
| |
| "//div[@class='palette']//input[@type='hidden']", |
| |
| "//div[@class='palette-available']//select", |
| |
| "//div[@class='palette-selected']//select", |
| |
| "//input[@name='checklist']", |
| |
| // TAP5-2078 |
| "//input[@name='radiogroup']", |
| |
| "//input[@id='submit_0']"}; |
| |
| for (String path : paths) |
| { |
| String locator = String.format("%s/@disabled", path); |
| |
| assertAttribute(locator, "disabled"); |
| } |
| |
| assertAttribute("css=div.palette .btn@disabled", "true"); |
| |
| //TAP5-2078 |
| clickAndWait("//input[@value='Continue']"); |
| |
| assertFalse(isTextPresent("This should not happen")); |
| } |
| |
| /** |
| * TAPESTRY-2056 |
| */ |
| @Test |
| public void null_field_strategy() |
| { |
| openLinks("Null Field Strategy Demo"); |
| |
| String locator = "//span[@id='value']"; |
| |
| assertText(locator, ""); |
| |
| assertAttribute("//input[@id='number']/@value", "0"); |
| |
| type("number", ""); |
| |
| clickAndWait(SUBMIT); |
| |
| assertText(locator, "0"); |
| } |
| |
| /** |
| * TAPESTRY-1647 |
| */ |
| @Test |
| public void label_invokes_validation_decorator_at_correct_time() |
| { |
| openLinks("Override Validation Decorator"); |
| |
| // This is sub-optimal, as it doesn't esnure that the before/after field |
| // values really do wrap around |
| // the field (they do, but that's hard to prove!). It is also susceptible to |
| // idiosyncrasies around how Tapestry renders attributes, and how the browser |
| // represents them. |
| |
| // Along the way we are also testing: |
| // - primitive types are automatically required |
| // - AbstractTextField.isRequired() and the logic inside |
| // ComponentFieldValidator.isRequired() |
| |
| assertSourcePresent( |
| "[Before label for Value]<label for=\"value\" class=\"control-label\">Value</label>[After label for Value]", |
| "[Before field Value]", |
| "[After field Value (optional)]", |
| "[Before label for Required Value]<label for=\"requiredValue\" class=\"control-label\">Required Value</label>[After label for Required Value]", |
| "[Before field Required Value]", "[After field Required Value (required)]"); |
| } |
| |
| /** |
| * TAPESTRY-2085 |
| */ |
| @Test |
| public void wrapper_types_with_text_field() |
| { |
| openLinks("TextField Wrapper Types", "Reset Page State"); |
| |
| assertFieldValue("count", ""); |
| assertText("value", "null"); |
| |
| type("count", "0"); |
| clickAndWait(SUBMIT); |
| |
| assertFieldValue("count", "0"); |
| assertText("value", "0"); |
| |
| type("count", "1"); |
| clickAndWait(SUBMIT); |
| |
| assertFieldValue("count", "1"); |
| assertText("value", "1"); |
| |
| clickAndWait("link=clear"); |
| |
| assertFieldValue("count", ""); |
| assertText("value", "null"); |
| } |
| |
| @Test |
| public void submit_with_context() |
| { |
| openLinks("Submit With Context"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("Result: 10.14159"); |
| } |
| |
| /** |
| * TAPESTRY-2563 |
| */ |
| @Test |
| public void form_action_via_get() |
| { |
| open(getBaseURL() + "validform.form", "true"); |
| |
| assertTextPresent("Forms require that the request method be POST and that the t:formdata query parameter have values."); |
| } |
| |
| /** |
| * TAPESTRY-2352 |
| */ |
| @Test |
| public void client_field_format_validation() |
| { |
| openLinks("Client Format Validation"); |
| |
| type("amount", "abc"); |
| type("quantity", "abc"); |
| |
| click(SUBMIT); |
| |
| assertTextPresent("You must provide a numeric value for Amount.", |
| "Provide quantity as a number."); |
| } |
| |
| /** |
| * TAPESTRY-2438 |
| */ |
| @Test |
| public void validation_exception_thrown_from_validate_form_event_handler() |
| { |
| openLinks("ValidationForm ValidationException Demo"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("From event handler method."); |
| |
| assertText("event", "failure"); |
| } |
| |
| @Test |
| public void form_field_outside_form() |
| { |
| openLinks("Form Field Outside Form"); |
| |
| assertTextPresent( |
| "org.apache.tapestry5.internal.services.RenderQueueException", |
| "Render queue error in SetupRender[FormFieldOutsideForm:textfield]: Component FormFieldOutsideForm:textfield must be enclosed by a Form component.", |
| "context:FormFieldOutsideForm.tml, line 5"); |
| } |
| |
| /** |
| * TAP5-281 |
| */ |
| @Test |
| public void nested_form_check() |
| { |
| openLinks("Nested Form Demo"); |
| |
| assertTextPresent("Form components may not be placed inside other Form components."); |
| } |
| |
| /** |
| * TAP5-87 |
| */ |
| @Test |
| public void blank_password_does_not_update() |
| { |
| openLinks("Blank Password Demo"); |
| |
| type("password", "secret"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertFieldValue("password", ""); |
| |
| assertText("visiblepassword", "secret"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertFieldValue("password", ""); |
| |
| assertText("visiblepassword", "secret"); |
| } |
| |
| /** |
| * TAP5-228: And to think I almost blew off the integration tests! |
| */ |
| @Test |
| public void per_form_validation_messages_and_constraints() |
| { |
| openLinks("Per-Form Validation Messages"); |
| |
| clickAndWait("//input[@type='submit' and @value='Login']"); |
| |
| assertTextPresent("Enter the unique user id you provided when you registerred."); |
| |
| type("userId", "aaa"); |
| |
| clickAndWait("//input[@type='submit' and @value='Login']"); |
| |
| assertTextPresent("You must provide at least 10 characters for User Id."); |
| |
| clickAndWait("//input[@type='submit' and @value='Register']"); |
| |
| assertTextPresent("Enter a unique user id, such as your initials."); |
| |
| type("userId_0", "aaa"); |
| |
| clickAndWait("//input[@type='submit' and @value='Register']"); |
| |
| assertTextPresent("You must provide at least 20 characters for User Id."); |
| } |
| |
| /** |
| * TAP5-719 |
| */ |
| @Test |
| public void link_submit_without_validator() |
| { |
| openLinks("LinkSubmit Without Validator Demo"); |
| |
| type("searchField", "Anders Haraldsson"); |
| |
| clickAndWait("//a[@id='searchLink']"); |
| |
| assertTextPresent("Result: Anders Haraldsson not found!"); |
| } |
| |
| /** |
| * TAP5-211 |
| */ |
| @Test |
| public void client_side_numeric_validation() |
| { |
| openLinks("Client-Side Numeric Validation", "Reset Page State", "Setup Values"); |
| |
| assertText("outputLongValue", "1000"); |
| assertText("outputDoubleValue", "1234.67"); |
| |
| assertFieldValue("longValue", "1000"); |
| assertFieldValue("doubleValue", "1,234.67"); |
| |
| type("longValue", "2,000 "); |
| type("doubleValue", " -456,789.12"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertText("outputLongValue", "2000"); |
| assertText("outputDoubleValue", "-456789.12"); |
| |
| assertFieldValue("longValue", "2000"); |
| assertFieldValue("doubleValue", "-456,789.12"); |
| |
| clickAndWait("link=Switch to German"); |
| |
| assertText("outputLongValue", "2000"); |
| assertText("outputDoubleValue", "-456789.12"); |
| |
| assertFieldValue("longValue", "2000"); |
| assertFieldValue("doubleValue", "-456.789,12"); |
| |
| type("longValue", "3.000"); |
| type("doubleValue", "5.444.333,22"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertFieldValue("longValue", "3000"); |
| assertFieldValue("doubleValue", "5.444.333,22"); |
| |
| assertText("outputLongValue", "3000"); |
| assertText("outputDoubleValue", "5444333.22"); |
| |
| clickAndWait("link=Setup Values"); |
| |
| type("longValue", "4000."); |
| click(SUBMIT); |
| |
| assertTextPresent("You must provide an integer value for Long Value."); |
| |
| type("doubleValue", "abc"); |
| |
| click(SUBMIT); |
| |
| assertTextPresent("You must provide a numeric value for Double Value."); |
| } |
| |
| @Test |
| public void client_validation_for_numeric_fields_that_are_not_required() |
| { |
| openLinks("Form Zone Demo"); |
| |
| type("longValue", "alpha"); |
| |
| click(SUBMIT); |
| |
| assertTextPresent("You must provide an integer value for Long Value."); |
| |
| type("longValue", "37"); |
| |
| click(SUBMIT); |
| |
| waitForElementToAppear("outputvalue"); |
| |
| assertText("outputvalue", "37"); |
| } |
| |
| @Test |
| public void hidden_field() |
| { |
| openLinks("Hidden Demo", "setup"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertText("stored", "12345"); |
| } |
| |
| @Test |
| public void validation_constraints_from_messages() |
| { |
| openLinks("Validation Constraints From Messages"); |
| |
| click(SUBMIT); |
| |
| assertTextPresent("You must provide a value for Name."); |
| assertTextPresent("You must provide a value for Age."); |
| |
| type("name", "behemoth"); |
| type("age", "0"); |
| select("type", "label=Snake"); |
| |
| click(SUBMIT); |
| assertTextPresent("Age requires a value of at least 1."); |
| |
| type("age", "121"); |
| click(SUBMIT); |
| assertTextPresent("Age requires a value no larger than 120."); |
| |
| type("age", "5"); |
| clickAndWait(SUBMIT); |
| } |
| |
| /** |
| * TAP5-157 |
| */ |
| @Test |
| public void link_submit_component() |
| { |
| openLinks("LinkSubmit Demo"); |
| |
| click("//a[@id='fred']"); |
| |
| assertTextPresent("You must provide a value for Name."); |
| |
| type("name", "Wilma"); |
| |
| clickAndWait("link=Fred"); |
| |
| assertText("name-value", "Wilma"); |
| assertText("last-clicked", "Fred"); |
| assertTextPresent("Result: 10.14159"); |
| |
| type("name", "Betty"); |
| |
| clickAndWait("link=Barney"); |
| |
| assertText("name-value", "Betty"); |
| assertText("last-clicked", "Barney"); |
| } |
| |
| /** |
| * TAP5-2183 |
| */ |
| @Test |
| public void link_submit_component_with_nested_element() |
| { |
| openLinks("LinkSubmit Demo"); |
| |
| type("name", "Wilma"); |
| |
| clickAndWait("css=.glyphicon-star"); |
| |
| assertText("name-value", "Wilma"); |
| assertText("last-clicked", "Pebbles"); |
| } |
| |
| @Test |
| public void calendar_field_inside_bean_editor() |
| { |
| openLinks("BeanEditor / Calendar Demo", "Reset Page State"); |
| |
| type("calendar", "04/06/1978"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("Apr 6, 1978"); |
| |
| // TAP5-1043 |
| clickAndWait("link=clear"); |
| } |
| |
| @Test |
| public void image_submit_triggers_selected_event() |
| { |
| openLinks("Submit with an Image Demo"); |
| |
| type("value", "barney gumble"); |
| |
| clickAndWait("//input[@type='image']"); |
| |
| assertText("outputvalue", "barney gumble"); |
| |
| assertText("eventfired", "true"); |
| } |
| |
| /** |
| * Tests for forms and form submissions and basic form control components. |
| * also tests a few other things, such as |
| * computed default bindings and invisible instrumentation. |
| */ |
| @Test |
| public void simple_form() |
| { |
| openLinks("SimpleForm"); |
| |
| assertText("//label[@for='disabled']", "Disabled"); |
| |
| // This demonstrates TAPESTRY-1642: |
| assertText("//label[@for='email']", "User Email"); |
| |
| assertText("//label[@for='message']", "Incident Message"); |
| assertText("//label[@for='operatingSystem']", "Operating System"); |
| assertText("//label[@for='department']", "Department"); |
| assertText("//label[@for='urgent']", "Urgent Processing Requested"); |
| |
| assertFieldValue("email", ""); |
| assertFieldValue("message", ""); |
| assertFieldValue("operatingSystem", "osx"); |
| assertFieldValue("department", ""); |
| assertFieldValue("urgent", "on"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("department: []"); |
| |
| type("email", "foo@bar.baz"); |
| type("message", "Message for you, sir!"); |
| select("operatingSystem", "Windows NT"); |
| select("department", "R&D"); |
| click("urgent"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertFieldValue("email", "foo@bar.baz"); |
| assertFieldValue("message", "Message for you, sir!"); |
| assertFieldValue("urgent", "off"); |
| |
| // Tried to use "email:" and "exact:email:" but Selenium 0.8.1 doesn't |
| // seem to accept that. |
| |
| assertTextPresent("[foo@bar.baz]", "[Message for you, sir!]", "[false]", "[winnt]", "[RESEARCH_AND_DESIGN]"); |
| |
| // Haven't figured out how to get selenium to check that fields are |
| // disabled. |
| } |
| |
| /** |
| * TAP5-915 |
| */ |
| @Test |
| public void override_datefield_message_catalog() |
| { |
| open(getBaseURL() + "overridedatefieldmessagecatalogdemo"); |
| |
| type("birthday", "aaaaa"); |
| |
| clickAndWait("//input[@type='submit' and @value='Go']"); |
| |
| assertTextPresent("The input 'aaaaa' is not a valid date"); |
| } |
| |
| /** |
| * TAP5-52. |
| */ |
| @Test |
| public void single_error_message() |
| { |
| open(getBaseURL() + "singleerrordemo"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("You must provide a value for Username"); |
| assertTextPresent("You must provide a value for Password"); |
| |
| type("username", "Igor"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertFalse(isTextPresent("You must provide a value for Username")); |
| assertTextPresent("You must provide a value for Password"); |
| |
| type("password", "secret"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertFalse(isTextPresent("You must provide a value for Username")); |
| assertFalse(isTextPresent("You must provide a value for Password")); |
| } |
| |
| /** |
| * TAP5-1024 |
| */ |
| @Test |
| public void use_of_cancel_mode_on_submit_button() |
| { |
| openLinks("Cancel Demo"); |
| |
| clickAndWait("//input[@value='Cancel Form']"); |
| |
| assertText("message", "Form was canceled."); |
| } |
| |
| @Test |
| public void use_of_cancel_mode_with_submitlink() |
| { |
| openLinks("Cancel Demo"); |
| |
| clickAndWait("link=Cancel Form"); |
| |
| assertText("message", "Form was canceled."); |
| } |
| |
| @Test |
| public void validation_decoration_for_select() throws Exception |
| { |
| openLinks("Select Demo"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("You must provide a value for Color."); |
| |
| select("color", "label=Green"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("Selected color: Green"); |
| } |
| |
| /** |
| * TAP5-1098. |
| */ |
| @Test |
| public void create_select_model_from_objects_and_property_name() throws Exception |
| { |
| openLinks("SelectModel from objects and property name"); |
| |
| select("track", "label=The Calling"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("Selected track: The Calling, Synaesthetic"); |
| } |
| |
| @Test |
| public void create_select_model_from_objects() throws Exception |
| { |
| openLinks("SelectModel from objects"); |
| |
| select("track", "label=The Calling"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("Selected track: The Calling, Synaesthetic"); |
| } |
| |
| @Test |
| public void create_select_model_coercion() throws Exception |
| { |
| openLinks("SelectModel coercion"); |
| |
| select("track", "label=The Calling"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("Selected track: The Calling, Synaesthetic"); |
| } |
| |
| @Test |
| public void validation_macro() throws Exception |
| { |
| openLinks("Validator Macro Demo"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("You must provide a value for Password."); |
| assertTextPresent("You must provide a value for Password2."); |
| |
| type("password", "abcdefg"); |
| type("password2", "x"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("You may provide at most 3 characters for Password."); |
| assertTextPresent("You must provide at least 2 characters for Password2."); |
| |
| type("password", "a"); |
| type("password2", "wxyz"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("You must provide at least 2 characters for Password."); |
| assertTextPresent("You may provide at most 3 characters for Password2."); |
| |
| type("password", "ab"); |
| type("password2", "xyz"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("Password: ab"); |
| assertTextPresent("Password2: xyz"); |
| } |
| |
| @Test |
| public void checklist_select() throws Exception |
| { |
| openLinks("Checklist Demo"); |
| |
| clickAndWait(SUBMIT); |
| assertTextPresent("You must provide a value for Color."); |
| |
| check("//input[@value='Green']"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("Selected colors: [Green]"); |
| |
| check("//input[@value='Red']"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("Selected colors: [Green, Red]"); |
| |
| check("//input[@value='Blue']"); |
| uncheck("//input[@value='Green']"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("Selected colors: [Blue, Red]"); |
| } |
| |
| @Test |
| public void checkFormLinkParameters() throws Exception |
| { |
| openLinks("FormLinkParameters Demo"); |
| assertAttribute("//input[@name='myparam']/@value", "!@#$%^&*()_+="); |
| |
| clickAndWait("link=SetValue"); |
| assertTextPresent("Result = '!@#$%^&*()_+='"); |
| |
| clickAndWait(SUBMIT); |
| assertTextPresent("Result = '!@#$%^&*()_+='"); |
| } |
| |
| /** |
| * TAP5-2223. |
| */ |
| @Test |
| public void optionGroup_form() |
| { |
| openLinks("OptionGroupForm Demo"); |
| |
| assertTextPresent("entity.id: [1]"); |
| |
| select("entity", "label2"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("entity.id: [2]"); |
| } |
| |
| /** TAP5-2331 */ |
| @Test |
| public void form_fields_client_id_parameter() |
| { |
| final String[] clientIds = {"clientId-0", "clientId-1"}; |
| |
| openLinks("Form Field clientId Parameter Demo"); |
| |
| for (int i = 0; i < 4; i++) { |
| |
| for (String clientId : clientIds) |
| { |
| assertTrue(selenium.isElementPresent(clientId)); |
| } |
| |
| click("updateZone"); |
| waitForAjaxRequestsToComplete(); |
| |
| } |
| |
| } |
| |
| /** TAP5-2301 */ |
| @Test |
| public void select_context() { |
| |
| openLinks("MultiZone Update inside a Form"); |
| selenium.select("selectValue1", "label=3 pre ajax"); |
| waitForAjaxRequestsToComplete(); |
| assertEquals( |
| "4 post ajax, number 013, retention policy RUNTIME", |
| selenium.getText("//select[@id='selectValue2']/option")); |
| |
| } |
| |
| /** TAP5-1815. In this webapp, HTML5 support is disabled, so we check whether it actually is disabled */ |
| @Test |
| public void html5_support_disabled() throws Exception |
| { |
| openLinks("ValidForm"); |
| assertEquals("text", getAttribute("emailValidator@type")); // if HTML5 support was enabled, this would be "email" |
| } |
| |
| /** TAP5-736 **/ |
| @Test |
| public void textfield_requires_non_null_validate_parameter() throws Exception |
| { |
| openLinks("TextField with null validate parameter"); |
| if(isTextPresent("java.lang.NullPointerException")){ |
| reportAndThrowAssertionError("Unexpected NullPointerException was thrown"); |
| } |
| assertTextPresent("This parameter is not allowed to be null."); |
| } |
| |
| /** TAP5-2467 **/ |
| @Test |
| public void validate_in_error_event() { |
| openLinks("Validate in error Event"); |
| |
| click(SUBMIT); |
| |
| waitForElementToAppear("validate-in-error"); |
| |
| assertTextPresent("Validate in error"); |
| } |
| |
| // TAP5-2204 |
| @Test |
| public void select_model_with_auto_security_and_non_persistent_model() throws Exception |
| { |
| openLinks("Select Demo"); |
| |
| select("month", "label=August"); |
| |
| clickAndWait(SUBMIT); |
| |
| assertTextPresent("Selected month: August"); |
| } |
| } |