diff options
author | Tarek Oraby <42799254+tarekoraby@users.noreply.github.com> | 2021-04-28 17:47:32 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-28 17:47:32 +0300 |
commit | 8c11cc6c9210e41b1e9981a04e56dd59d462da91 (patch) | |
tree | 9bcbfcf705f3217621144e2b951814401617139f /uitest | |
parent | 83ee08eae1a9997298713a6302dc929cc98dedfc (diff) | |
download | vaadin-framework-8c11cc6c9210e41b1e9981a04e56dd59d462da91.tar.gz vaadin-framework-8c11cc6c9210e41b1e9981a04e56dd59d462da91.zip |
Fix validation in non-buffered Grid editor (#12281)
Handle possible race condition by disabling the editor's widget while awaiting validation from the server.
Fixes #12270
Diffstat (limited to 'uitest')
-rw-r--r-- | uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorNonBuffered.java | 103 | ||||
-rw-r--r-- | uitest/src/test/java/com/vaadin/tests/components/grid/GridEditorNonBufferedTest.java | 99 |
2 files changed, 202 insertions, 0 deletions
diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorNonBuffered.java b/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorNonBuffered.java new file mode 100644 index 0000000000..adf49d3870 --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorNonBuffered.java @@ -0,0 +1,103 @@ +package com.vaadin.tests.components.grid; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import java.util.Random; + +import com.vaadin.data.Binder; +import com.vaadin.data.Binder.Binding; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractReindeerTestUIWithLog; +import com.vaadin.tests.util.Person; +import com.vaadin.tests.util.TestDataGenerator; +import com.vaadin.ui.Grid; +import com.vaadin.ui.Grid.Column; +import com.vaadin.ui.TextField; +import com.vaadin.ui.renderers.NumberRenderer; + +public class GridEditorNonBuffered extends AbstractReindeerTestUIWithLog { + + final static String VALIDATION_ERROR_MESSAGE = "Validator error. Name cannot be empty"; + + @Override + protected void setup(VaadinRequest request) { + Grid<Person> grid = createGrid(); + grid.setItems(createTestData()); + addComponent(grid); + } + + protected Collection<Person> createTestData() { + return createTestData(100); + } + + protected Collection<Person> createTestData(int size) { + Random r = new Random(0); + List<Person> testData = new ArrayList<>(); + for (int i = 0; i < size; i++) { + Person person = new Person(); + person.setFirstName(TestDataGenerator.getFirstName(r)); + person.setLastName(TestDataGenerator.getLastName(r)); + person.getAddress().setCity(TestDataGenerator.getCity(r)); + person.setEmail(person.getFirstName().toLowerCase(Locale.ROOT) + "." + + person.getLastName().toLowerCase(Locale.ROOT) + + "@vaadin.com"); + person.setPhoneNumber(TestDataGenerator.getPhoneNumber(r)); + + person.getAddress() + .setPostalCode(TestDataGenerator.getPostalCode(r)); + person.getAddress() + .setStreetAddress(TestDataGenerator.getStreetAddress(r)); + testData.add(person); + } + return testData; + } + + protected Grid<Person> createGrid() { + Grid<Person> grid = new Grid<>(); + + grid.addColumn(Person::getEmail).setCaption("Email").setId("email"); + + Column<Person, String> firstNameColumn = grid + .addColumn(Person::getFirstName).setCaption("First Name") + .setId("firstName"); + Column<Person, String> lastNameColumn = grid + .addColumn(Person::getLastName).setCaption("Last Name") + .setId("lastName"); + + grid.addColumn(Person::getPhoneNumber).setCaption("Phone Number") + .setId("phone"); + grid.addColumn(person -> person.getAddress().getStreetAddress()) + .setCaption("Street Address").setId("street"); + grid.addColumn(person -> person.getAddress().getPostalCode(), + new NumberRenderer()).setCaption("Postal Code").setId("zip"); + grid.addColumn(person -> person.getAddress().getCity()) + .setCaption("City").setId("city"); + + Binder<Person> binder = new Binder<>(); + + TextField firstNameEditor = new TextField(); + Binding<Person, String> firstNamebinding = binder + .forField(firstNameEditor) + .withValidator(v -> (v != null && !v.isEmpty()), + VALIDATION_ERROR_MESSAGE) + .bind(Person::getFirstName, Person::setFirstName); + firstNameColumn.setEditorBinding(firstNamebinding); + + TextField lastNameEditor = new TextField(); + Binding<Person, String> lastNamebinding = binder + .forField(lastNameEditor) + .withValidator(v -> (v != null && !v.isEmpty()), + VALIDATION_ERROR_MESSAGE) + .bind(Person::getLastName, Person::setLastName); + lastNameColumn.setEditorBinding(lastNamebinding); + + grid.getEditor().setBuffered(false); + grid.getEditor().setEnabled(true); + grid.getEditor().setBinder(binder); + + return grid; + } + +} diff --git a/uitest/src/test/java/com/vaadin/tests/components/grid/GridEditorNonBufferedTest.java b/uitest/src/test/java/com/vaadin/tests/components/grid/GridEditorNonBufferedTest.java new file mode 100644 index 0000000000..eaa88adcbc --- /dev/null +++ b/uitest/src/test/java/com/vaadin/tests/components/grid/GridEditorNonBufferedTest.java @@ -0,0 +1,99 @@ +package com.vaadin.tests.components.grid; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +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.testbench.elements.GridElement; +import com.vaadin.testbench.elements.GridElement.GridCellElement; +import com.vaadin.testbench.elements.NotificationElement; +import com.vaadin.testbench.elements.TextFieldElement; +import com.vaadin.testbench.parallel.TestCategory; +import com.vaadin.tests.tb3.MultiBrowserTest; + +@TestCategory("grid") +public class GridEditorNonBufferedTest extends MultiBrowserTest { + + @Override + public void setup() throws Exception { + super.setup(); + + setDebug(true); + openTestURL(); + } + + private void openEditor(int rowIndex, int cellIndex) { + GridElement grid = $(GridElement.class).first(); + GridCellElement cell = grid.getCell(rowIndex, cellIndex); + new Actions(driver).moveToElement(cell).doubleClick().build().perform(); + } + + @Test + public void testEditor() { + openEditor(5, 1); + + assertTrue("Editor should be opened with a TextField", + isElementPresent(TextFieldElement.class)); + + assertFalse("Notification was present", + isElementPresent(NotificationElement.class)); + } + + @Test + public void testEscClosesEditor() { + openEditor(5, 1); + + assertTrue("Editor should be opened with a TextField", + isElementPresent(TextFieldElement.class)); + + new Actions(getDriver()).sendKeys(Keys.ESCAPE).perform(); + + assertFalse("Editor should be closed", + isElementPresent(TextFieldElement.class)); + } + + @Test + public void preventNavigationToNextRowIfEditorValueIsInvalid() { + // Test with navigation to next row + openEditor(5, 2); + WebElement field = findElement(By.className("v-textfield-focus")); + String selectAll = Keys.chord(Keys.CONTROL, "a"); + field.sendKeys(selectAll); + field.sendKeys(Keys.DELETE); + field.sendKeys(Keys.TAB); + + String editorMessage = getEditorMessage(); + + assertEquals( + "Last Name: " + GridEditorNonBuffered.VALIDATION_ERROR_MESSAGE, + editorMessage); + } + + @Test + public void preventNavigationToPrevRowIfEditorValueIsInvalid() { + // Test with navigation to previous row + openEditor(5, 1); + WebElement field = findElement(By.className("v-textfield-focus")); + String selectAll = Keys.chord(Keys.CONTROL, "a"); + field.sendKeys(selectAll); + field.sendKeys(Keys.DELETE); + field.sendKeys(Keys.chord(Keys.SHIFT, Keys.TAB)); + String editorMessage = getEditorMessage(); + + assertEquals( + "First Name: " + GridEditorNonBuffered.VALIDATION_ERROR_MESSAGE, + editorMessage); + } + + private String getEditorMessage() { + return findElement( + By.xpath("//div[@class = 'v-grid-editor-message']/div")) + .getText(); + } +} |