Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Related to #7799
- Loading branch information
Showing
2 changed files
with
292 additions
and
0 deletions.
There are no files selected for viewing
140 changes: 140 additions & 0 deletions
140
flow-tests/test-root-context/src/main/java/com/vaadin/flow/uitest/ui/ModalDialogView.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
/* | ||
* Copyright 2000-2020 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.flow.uitest.ui; | ||
|
||
import com.vaadin.flow.component.ClickEvent; | ||
import com.vaadin.flow.component.Component; | ||
import com.vaadin.flow.component.ComponentEventListener; | ||
import com.vaadin.flow.component.Key; | ||
import com.vaadin.flow.component.Text; | ||
import com.vaadin.flow.component.UI; | ||
import com.vaadin.flow.component.html.Div; | ||
import com.vaadin.flow.component.html.Input; | ||
import com.vaadin.flow.component.html.NativeButton; | ||
import com.vaadin.flow.router.Route; | ||
|
||
@Route(value = "com.vaadin.flow.uitest.ui.ModalDialogView") | ||
public class ModalDialogView extends Div { | ||
|
||
public static final String EVENT_LOG = "event-log"; | ||
public static final String UI_BUTTON = "ui-button"; | ||
public static final String OPEN_MODELESS_BUTTON = "modeless-dialog-button"; | ||
public static final String OPEN_MODAL_BUTTON = "modal-dialog-button"; | ||
public static final String DIALOG_BUTTON = "dialog-button"; | ||
public static final String DIALOG_CLOSE_BUTTON = "dialog-close-button"; | ||
public static final String DIALOG = "DIALOG"; | ||
public static final String LISTEN_ON_UI_BUTTON = "listen-on-ui-button"; | ||
public static final String LISTEN_ON_DIALOG_BUTTON = "listen-on-dialog-button"; | ||
public static final Key SHORTCUT_KEY = Key.KEY_X; | ||
private int eventCounter; | ||
private final Div eventLog; | ||
|
||
public ModalDialogView() { | ||
eventLog = new Div(new Text("Click events and their sources:")); | ||
eventLog.setId(EVENT_LOG); | ||
|
||
final NativeButton testButton = createButton("Key-X shortcut", | ||
this::logClickEvent); | ||
testButton.setId(UI_BUTTON); | ||
testButton.addClickShortcut(SHORTCUT_KEY); | ||
|
||
add(createOpenDialogButton(true, OPEN_MODAL_BUTTON), | ||
createOpenDialogButton(false, OPEN_MODELESS_BUTTON), testButton, | ||
eventLog); | ||
setId("main-div"); | ||
} | ||
|
||
private void logClickEvent(ClickEvent<?> event) { | ||
eventLog.addComponentAsFirst(new Div(new Text((eventCounter++) + "-" | ||
+ event.getSource().getId().orElse("NO-SOURCE-ID")))); | ||
} | ||
|
||
private Component createOpenDialogButton(boolean modal, String id) { | ||
final NativeButton button = createButton( | ||
"Open " + (modal ? "modal" : "non-modal") + " dialog", | ||
event -> { | ||
final Dialog dialog = new Dialog(modal); | ||
dialog.open(); | ||
}); | ||
button.setId(id); | ||
return button; | ||
} | ||
|
||
private NativeButton createButton(String caption, | ||
ComponentEventListener<ClickEvent<NativeButton>> listener) { | ||
final NativeButton button = new NativeButton(); | ||
button.setText(caption); | ||
button.addClickListener(listener); | ||
button.getStyle().set("border", "1px solid black"); | ||
button.setWidth("100px"); | ||
return button; | ||
} | ||
|
||
public class Dialog extends Div { | ||
private boolean modal; | ||
|
||
public Dialog(boolean modal) { | ||
this.modal = modal; | ||
|
||
final NativeButton testButton = createButton( | ||
"Test button with enter shortcut", | ||
ModalDialogView.this::logClickEvent); | ||
testButton.setId(DIALOG_BUTTON); | ||
final NativeButton uiScopeShortcutButton = new NativeButton( | ||
"Add shortcut with listenOn(UI)", event -> { | ||
testButton.addClickShortcut(SHORTCUT_KEY); | ||
event.getSource().setEnabled(false); | ||
}); | ||
uiScopeShortcutButton.setId(LISTEN_ON_UI_BUTTON); | ||
final NativeButton dialogScopeShortcutButton = new NativeButton( | ||
"Add shortcut with listenOn(Dialog)", event -> { | ||
testButton.addClickShortcut(SHORTCUT_KEY) | ||
.listenOn(Dialog.this); | ||
event.getSource().setEnabled(false); | ||
}); | ||
dialogScopeShortcutButton.setId(LISTEN_ON_DIALOG_BUTTON); | ||
|
||
final Component closeButton = createButton("Close", | ||
event -> close()); | ||
closeButton.setId(DIALOG_CLOSE_BUTTON); | ||
add(new Text("A " + (modal ? "modal" : "modeless") + " dialog"), | ||
new Input(), new Div(), closeButton, uiScopeShortcutButton, | ||
dialogScopeShortcutButton, new Div(), testButton); | ||
|
||
getUI().ifPresent(ui -> { | ||
ui.setChildComponentModal(this, modal); | ||
}); | ||
getStyle().set("position", "fixed").set("inset", "50% 50%") | ||
.set("border", "1px solid black"); | ||
setId(DIALOG); | ||
} | ||
|
||
public void open() { | ||
final UI ui = ModalDialogView.this.getUI().get(); | ||
if (modal) { | ||
ui.addModal(this); | ||
} else { | ||
ui.add(this); | ||
} | ||
} | ||
|
||
public void close() { | ||
final UI ui = ModalDialogView.this.getUI().get(); | ||
ui.remove(this); | ||
} | ||
} | ||
} |
152 changes: 152 additions & 0 deletions
152
flow-tests/test-root-context/src/test/java/com/vaadin/flow/uitest/ui/ModalDialogIT.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
package com.vaadin.flow.uitest.ui; | ||
|
||
import com.vaadin.flow.component.html.testbench.DivElement; | ||
import com.vaadin.flow.component.html.testbench.NativeButtonElement; | ||
import com.vaadin.flow.testutil.ChromeBrowserTest; | ||
import com.vaadin.testbench.TestBenchElement; | ||
import org.junit.Assert; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
import org.openqa.selenium.By; | ||
import org.openqa.selenium.WebElement; | ||
|
||
public class ModalDialogIT extends ChromeBrowserTest { | ||
|
||
private TestBenchElement eventLog; | ||
private TestBenchElement modalDialogButton; | ||
private TestBenchElement modelessDialogButton; | ||
|
||
@Before | ||
public void init() { | ||
open(); | ||
eventLog = $(DivElement.class).id(ModalDialogView.EVENT_LOG); | ||
modalDialogButton = $(NativeButtonElement.class) | ||
.id(ModalDialogView.OPEN_MODAL_BUTTON); | ||
modelessDialogButton = $(NativeButtonElement.class) | ||
.id(ModalDialogView.OPEN_MODELESS_BUTTON); | ||
} | ||
|
||
// #7799 | ||
@Test | ||
public void modalDialogOpened_sameShortcutsListeningOnUi_noShortcutTriggered() { | ||
pressShortcutKey( | ||
$(NativeButtonElement.class).id(ModalDialogView.UI_BUTTON)); | ||
validateLatestShortcutEvent(0, ModalDialogView.UI_BUTTON); | ||
|
||
openDialog(modalDialogButton); | ||
pressShortcutKey(getDialogInput()); | ||
// no event occurred | ||
validateLatestShortcutEvent(0, ModalDialogView.UI_BUTTON); | ||
listenToButtonShortcutOnUI(); | ||
pressShortcutKey(getDialogInput()); | ||
// no event occurred since shortcut is listened on ui which is inept | ||
validateLatestShortcutEvent(0, ModalDialogView.UI_BUTTON); | ||
|
||
closeDialog(); | ||
pressShortcutKey( | ||
$(NativeButtonElement.class).id(ModalDialogView.UI_BUTTON)); | ||
validateLatestShortcutEvent(1, ModalDialogView.UI_BUTTON); | ||
} | ||
|
||
@Test | ||
public void modalDialogOpened_sameShortcutListeningOnUiAndDialog_onlyDialogShortcutExecuted() { | ||
pressShortcutKey( | ||
$(NativeButtonElement.class).id(ModalDialogView.UI_BUTTON)); | ||
validateLatestShortcutEvent(0, ModalDialogView.UI_BUTTON); | ||
|
||
openDialog(modalDialogButton); | ||
pressShortcutKey(getDialogInput()); | ||
// no event occurred | ||
validateLatestShortcutEvent(0, ModalDialogView.UI_BUTTON); | ||
|
||
listenToButtonShortcutOnDialog(); | ||
pressShortcutKey(getDialogInput()); | ||
validateLatestShortcutEvent(1, ModalDialogView.DIALOG_BUTTON); | ||
|
||
closeDialog(); | ||
pressShortcutKey( | ||
$(NativeButtonElement.class).id(ModalDialogView.UI_BUTTON)); | ||
validateLatestShortcutEvent(2, ModalDialogView.UI_BUTTON); | ||
} | ||
|
||
@Test | ||
public void modelessDialogOpened_sharesShortcutWithUI_bothExecuted() { | ||
pressShortcutKey( | ||
$(NativeButtonElement.class).id(ModalDialogView.UI_BUTTON)); | ||
validateLatestShortcutEvent(0, ModalDialogView.UI_BUTTON); | ||
|
||
openDialog(modelessDialogButton); | ||
listenToButtonShortcutOnUI(); | ||
pressShortcutKey(getDialogInput()); | ||
|
||
validateShortcutEvent(1, 1, ModalDialogView.UI_BUTTON); | ||
validateLatestShortcutEvent(2, ModalDialogView.DIALOG_BUTTON); | ||
|
||
closeDialog(); | ||
pressShortcutKey( | ||
$(NativeButtonElement.class).id(ModalDialogView.UI_BUTTON)); | ||
validateLatestShortcutEvent(3, ModalDialogView.UI_BUTTON); | ||
} | ||
|
||
@Test | ||
public void modelessDialogOpened_sameShortcutListeningOnUiAndDialog_bothExecuted() { | ||
pressShortcutKey( | ||
$(NativeButtonElement.class).id(ModalDialogView.UI_BUTTON)); | ||
validateLatestShortcutEvent(0, ModalDialogView.UI_BUTTON); | ||
|
||
openDialog(modelessDialogButton); | ||
listenToButtonShortcutOnDialog(); | ||
pressShortcutKey(getDialogInput()); | ||
|
||
validateLatestShortcutEvent(1, ModalDialogView.DIALOG_BUTTON); | ||
pressShortcutKey(getDialogInput()); | ||
validateLatestShortcutEvent(2, ModalDialogView.DIALOG_BUTTON); | ||
|
||
closeDialog(); | ||
pressShortcutKey( | ||
$(NativeButtonElement.class).id(ModalDialogView.UI_BUTTON)); | ||
validateLatestShortcutEvent(3, ModalDialogView.UI_BUTTON); | ||
} | ||
|
||
private void openDialog(WebElement modalDialogButton) { | ||
modalDialogButton.click(); | ||
} | ||
|
||
private void closeDialog() { | ||
$(NativeButtonElement.class).id(ModalDialogView.DIALOG_CLOSE_BUTTON) | ||
.click(); | ||
} | ||
|
||
private void validateLatestShortcutEvent(int eventCounter, | ||
String eventSourceId) { | ||
validateShortcutEvent(0, eventCounter, eventSourceId); | ||
} | ||
|
||
private void validateShortcutEvent(int indexFromTop, int eventCounter, | ||
String eventSourceId) { | ||
final WebElement latestEvent = eventLog.findElements(By.tagName("div")) | ||
.get(indexFromTop); | ||
Assert.assertEquals("Invalid latest event", | ||
eventCounter + "-" + eventSourceId, latestEvent.getText()); | ||
} | ||
|
||
private void pressShortcutKey(TestBenchElement elementToFocus) { | ||
elementToFocus.focus(); | ||
elementToFocus.sendKeys("x"); | ||
} | ||
|
||
private TestBenchElement getDialogInput() { | ||
return $(DivElement.class).id(ModalDialogView.DIALOG).$("input") | ||
.first(); | ||
} | ||
|
||
private void listenToButtonShortcutOnUI() { | ||
$(NativeButtonElement.class).id(ModalDialogView.LISTEN_ON_UI_BUTTON) | ||
.click(); | ||
} | ||
|
||
private void listenToButtonShortcutOnDialog() { | ||
$(NativeButtonElement.class).id(ModalDialogView.LISTEN_ON_DIALOG_BUTTON) | ||
.click(); | ||
} | ||
} |