Skip to content

Commit

Permalink
test: add ITs for modal dialogs
Browse files Browse the repository at this point in the history
Related to #7799
  • Loading branch information
pleku committed Mar 2, 2021
1 parent ed5dca7 commit 38d5c3f
Show file tree
Hide file tree
Showing 2 changed files with 292 additions and 0 deletions.
@@ -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);
}
}
}
@@ -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();
}
}

0 comments on commit 38d5c3f

Please sign in to comment.