summaryrefslogtreecommitdiffstats
path: root/uitest
diff options
context:
space:
mode:
authorTarek Oraby <42799254+tarekoraby@users.noreply.github.com>2021-04-28 17:47:32 +0300
committerGitHub <noreply@github.com>2021-04-28 17:47:32 +0300
commit8c11cc6c9210e41b1e9981a04e56dd59d462da91 (patch)
tree9bcbfcf705f3217621144e2b951814401617139f /uitest
parent83ee08eae1a9997298713a6302dc929cc98dedfc (diff)
downloadvaadin-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.java103
-rw-r--r--uitest/src/test/java/com/vaadin/tests/components/grid/GridEditorNonBufferedTest.java99
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();
+ }
+}