Change-Id: I412ba219f31567ebba019b7d6ce4db4af9be9363tags/7.5.0.beta1
@@ -0,0 +1,12 @@ | |||
<html> | |||
<head> | |||
<title>IEJumpTest</title> | |||
</head> | |||
<!-- This is for testing Vaadin UI in iFrame (test class TableInIframeRowClickScrollJumpTest, for ticket #15294 --> | |||
<body> | |||
<div style="font-size: 4px">test div</div> | |||
<iframe id="test-iframe-0" src="/run/com.vaadin.tests.components.table.TableBlurFocus" width="100%" height="2000px" style="visibility: visible;"> | |||
</iframe> | |||
</body> | |||
</html> |
@@ -48,9 +48,11 @@ public class FocusableScrollPanel extends SimpleFocusablePanel implements | |||
Style style = getElement().getStyle(); | |||
style.setProperty("zoom", "1"); | |||
style.setPosition(Position.RELATIVE); | |||
browserInfo = BrowserInfo.get(); | |||
} | |||
private DivElement focusElement; | |||
private BrowserInfo browserInfo; | |||
public FocusableScrollPanel(boolean useFakeFocusElement) { | |||
this(); | |||
@@ -72,6 +74,12 @@ public class FocusableScrollPanel extends SimpleFocusablePanel implements | |||
style.setPosition(Position.FIXED); | |||
style.setTop(0, Unit.PX); | |||
style.setLeft(0, Unit.PX); | |||
if (browserInfo.isIE()) { | |||
// for #15294: artificially hide little bit more the | |||
// focusElement, otherwise IE will make the window to scroll | |||
// into it when focused | |||
style.setLeft(-999, Unit.PX); | |||
} | |||
getElement().appendChild(focusElement); | |||
/* Sink from focusElemet too as focusa and blur don't bubble */ | |||
DOM.sinkEvents(focusElement, Event.FOCUSEVENTS); |
@@ -0,0 +1,153 @@ | |||
/* | |||
* 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 java.util.Map; | |||
import com.vaadin.event.FieldEvents.BlurEvent; | |||
import com.vaadin.event.FieldEvents.BlurListener; | |||
import com.vaadin.event.FieldEvents.FocusEvent; | |||
import com.vaadin.event.FieldEvents.FocusListener; | |||
import com.vaadin.server.VaadinRequest; | |||
import com.vaadin.tests.components.AbstractTestUIWithLog; | |||
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.Notification; | |||
import com.vaadin.ui.Table; | |||
/** | |||
* Tests that previously focused component's blur event happens before any | |||
* variable changes in the focused Table. | |||
* | |||
* @author Vaadin Ltd | |||
*/ | |||
public class TableBlurFocus extends AbstractTestUIWithLog { | |||
enum Columns { | |||
COLUMN1, COLUMN2, COLUMN3, COLUMN4, COLUMN5 | |||
} | |||
private int count = 0; | |||
private Button focusButton; | |||
@Override | |||
protected void setup(VaadinRequest request) { | |||
System.out | |||
.println("TableBlurFocus/TableInIframeRowClickScrollJumpTest"); | |||
Button button = new Button("click to focus"); | |||
button.addFocusListener(new FocusListener() { | |||
@Override | |||
public void focus(FocusEvent event) { | |||
log("focus"); | |||
} | |||
}); | |||
button.addBlurListener(new BlurListener() { | |||
@Override | |||
public void blur(BlurEvent event) { | |||
log("blur"); | |||
} | |||
}); | |||
final Button scrollButton = new Button( | |||
"focus lowest button to scroll down"); | |||
scrollButton.setId("scroll-button"); | |||
scrollButton.addClickListener(new ClickListener() { | |||
@Override | |||
public void buttonClick(ClickEvent event) { | |||
focusButton.focus(); | |||
} | |||
}); | |||
Label spacerLabel = new Label("spacer"); | |||
spacerLabel.setHeight("300px"); | |||
addComponent(button); | |||
addComponent(scrollButton); | |||
addComponent(createTable()); | |||
addComponent(spacerLabel); | |||
addComponent(focusButton = new Button("for focus")); | |||
focusButton.setId("focus-button"); | |||
focusButton.addFocusListener(new FocusListener() { | |||
@Override | |||
public void focus(FocusEvent event) { | |||
focusButton.setCaption("focused"); | |||
} | |||
}); | |||
} | |||
private Table createTable() { | |||
Table table = new Table() { | |||
@Override | |||
public void changeVariables(Object source, | |||
Map<String, Object> variables) { | |||
log("variable change"); | |||
super.changeVariables(source, variables); | |||
} | |||
}; | |||
table.setSelectable(true); | |||
table.setImmediate(true); | |||
table.addContainerProperty(Columns.COLUMN1, String.class, " "); | |||
table.addContainerProperty(Columns.COLUMN2, Label.class, null); | |||
table.addContainerProperty(Columns.COLUMN3, Button.class, null); | |||
table.addContainerProperty(Columns.COLUMN4, String.class, " "); | |||
table.setColumnCollapsingAllowed(true); | |||
table.setColumnCollapsible(Columns.COLUMN4, true); | |||
table.setColumnCollapsed(Columns.COLUMN4, true); | |||
table.setSortEnabled(true); | |||
table.setFooterVisible(true); | |||
table.setPageLength(14); | |||
table.addGeneratedColumn(Columns.COLUMN5, new Table.ColumnGenerator() { | |||
@Override | |||
public Object generateCell(Table source, Object itemId, | |||
Object columnId) { | |||
return "Generated"; | |||
} | |||
}); | |||
table.setColumnHeader(Columns.COLUMN1, "Column"); | |||
for (int x = 0; x < 120; x++) { | |||
final Label buttonLabel = new Label("Not clicked"); | |||
Button button = new Button("Click me?", new Button.ClickListener() { | |||
@Override | |||
public void buttonClick(Button.ClickEvent event) { | |||
++count; | |||
buttonLabel.setValue("Clicked " + count + " times"); | |||
Notification.show("Clicked!"); | |||
} | |||
}); | |||
table.addItem(new Object[] { "entryString" + x, buttonLabel, | |||
button, " " }, "entryID" + x); | |||
} | |||
return table; | |||
} | |||
@Override | |||
protected String getTestDescription() { | |||
return "Click button to focus, then click Table header. Blur event should arrive before the next variable change."; | |||
} | |||
@Override | |||
protected Integer getTicketNumber() { | |||
return 15294; | |||
} | |||
} |
@@ -0,0 +1,64 @@ | |||
/* | |||
* 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.MatcherAssert.assertThat; | |||
import static org.junit.Assert.assertEquals; | |||
import java.util.Arrays; | |||
import org.junit.Test; | |||
import org.openqa.selenium.By; | |||
import com.vaadin.testbench.elements.ButtonElement; | |||
import com.vaadin.testbench.elements.TableElement; | |||
import com.vaadin.tests.tb3.MultiBrowserTest; | |||
public class TableBlurFocusTest extends MultiBrowserTest { | |||
@Test | |||
public void testBlurAndFocus() throws InterruptedException { | |||
openTestURL(); | |||
waitForElementPresent(By.className("v-button")); | |||
assertAnyLogText("1. variable change"); | |||
assertEquals("Unexpected column header,", "COLUMN2", | |||
$(TableElement.class).first().getHeaderCell(1).getCaption()); | |||
assertEquals("Unexpected button caption,", "click to focus", | |||
$(ButtonElement.class).first().getCaption()); | |||
$(ButtonElement.class).first().click(); | |||
assertAnyLogText("2. focus", "3. focus"); | |||
$(TableElement.class).first().getHeaderCell(1).click(); | |||
assertAnyLogText("3. blur", "4. blur"); | |||
} | |||
private void assertAnyLogText(String... texts) { | |||
assertThat(String.format( | |||
"Correct log text was not found, expected any of %s", | |||
Arrays.asList(texts)), logContainsAnyText(texts)); | |||
} | |||
private boolean logContainsAnyText(String... texts) { | |||
for (String text : texts) { | |||
if (logContainsText(text)) { | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
} |
@@ -0,0 +1,127 @@ | |||
/* | |||
* 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.MatcherAssert.assertThat; | |||
import java.util.List; | |||
import org.junit.Test; | |||
import org.openqa.selenium.JavascriptExecutor; | |||
import org.openqa.selenium.WebElement; | |||
import com.vaadin.testbench.By; | |||
import com.vaadin.testbench.elements.ButtonElement; | |||
import com.vaadin.testbench.elements.TableElement; | |||
import com.vaadin.tests.tb3.MultiBrowserTest; | |||
/** | |||
* For testing that UI scroll does not jump back to up when: 1. UI is in iframe | |||
* 2. the window scrolled down 3. and table is clicked | |||
* | |||
* @since | |||
* @author Vaadin Ltd | |||
*/ | |||
public class TableInIframeRowClickScrollJumpTest extends MultiBrowserTest { | |||
private static final String TEST_URL = "statictestfiles/TableInIframeRowClickScrollJumpTest.html"; | |||
@Test | |||
public void testRowClicking_WhenScrolledDown_shouldMaintainScrollPosition() | |||
throws InterruptedException { | |||
System.out.println(">>>" + getBaseURL() + TEST_URL); | |||
driver.get(getUrl()); | |||
// using non-standard way because of iframe | |||
sleep(4000); | |||
// make sure we are in the "main content" | |||
driver.switchTo().defaultContent(); | |||
sleep(2000); | |||
switchIntoIframe(); | |||
// using non-standard way because of iframe | |||
waitForElementVisible(By.id("scroll-button")); | |||
ButtonElement scrollbutton = $(ButtonElement.class).id("scroll-button"); | |||
scrollbutton.click(); | |||
// using non-standard way because of iframe | |||
sleep(1000); | |||
Long scrollPosition = getWindowsScrollPosition(); | |||
assertThat("Scroll position should be greater than 100 (it was " | |||
+ scrollPosition + ")", scrollPosition > 100); | |||
TableElement table = $(TableElement.class).first(); | |||
table.getRow(13).getCell(0).click(); | |||
// using non-standard way because of iframe | |||
sleep(1000); | |||
Long scrollPosition2 = getWindowsScrollPosition(); | |||
assertThat("Scroll position should stay about the same. Old was " | |||
+ scrollPosition + " and new one " + scrollPosition2, | |||
Math.abs(scrollPosition - scrollPosition2) < 10); | |||
} | |||
private String getUrl() { | |||
String url; | |||
// using non-standard way because of iframe | |||
if (getBaseURL().charAt(getBaseURL().length() - 1) == '/') { | |||
url = getBaseURL() + TEST_URL; | |||
} else { | |||
// this one is for gerrit's teamcity :( | |||
url = getBaseURL() + '/' + TEST_URL; | |||
} | |||
return url; | |||
} | |||
public void switchIntoIframe() { | |||
List<WebElement> frames = driver.findElements(By.tagName("iframe")); | |||
assertThat("No frames was found", frames.size() > 0); | |||
driver.switchTo().frame(frames.get(0)); | |||
} | |||
private Long getWindowsScrollPosition() { | |||
// measure scroll pos in the main window | |||
driver.switchTo().defaultContent(); | |||
JavascriptExecutor executor = (JavascriptExecutor) driver; | |||
Long value = (Long) executor | |||
.executeScript("if (window.pageYOffset) return window.pageYOffset;else if (window.document.documentElement.scrollTop) return window.document.documentElement.scrollTop;else return window.document.body.scrollTop;"); | |||
// back to the iframe | |||
switchIntoIframe(); | |||
return value; | |||
} | |||
@Override | |||
// using non-standard way because of iframe | |||
protected void closeApplication() { | |||
if (driver != null) { | |||
try { | |||
driver.get(getUrl() + "?closeApplication"); | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
} | |||
} | |||
} | |||
} |