]> source.dussan.org Git - vaadin-framework.git/commitdiff
Back button doesn't change URL if view blocks the navigation (#10901)
authorAnna Miroshnik <anna.miroshnik@arcadia.spb.ru>
Thu, 11 Dec 2014 15:22:42 +0000 (18:22 +0300)
committerVaadin Code Review <review@vaadin.com>
Mon, 15 Dec 2014 11:06:57 +0000 (11:06 +0000)
Change-Id: Ib1211a7a2282753b329129615a544264e62d1ed5

server/src/com/vaadin/navigator/Navigator.java
uitest/src/com/vaadin/tests/navigator/NavigatorViewBlocksBackButtonAction.java [new file with mode: 0644]
uitest/src/com/vaadin/tests/navigator/NavigatorViewBlocksBackButtonActionTest.java [new file with mode: 0644]

index 80dad2244e968b34f34631f9f68a88a16958219d..591f73dc7542cdf85ecf7a0546e766842e2494a3 100644 (file)
@@ -371,6 +371,7 @@ public class Navigator implements Serializable {
     private View currentView = null;
     private List<ViewChangeListener> listeners = new LinkedList<ViewChangeListener>();
     private List<ViewProvider> providers = new LinkedList<ViewProvider>();
+    private String currentNavigationState = null;
     private ViewProvider errorProvider;
 
     /**
@@ -551,6 +552,11 @@ public class Navigator implements Serializable {
         ViewChangeEvent event = new ViewChangeEvent(this, currentView, view,
                 viewName, parameters);
         if (!fireBeforeViewChange(event)) {
+            // #10901. Revert URL to previous state if back-button navigation
+            // was canceled
+            if (currentNavigationState != null) {
+                getStateManager().setState(currentNavigationState);
+            }
             return;
         }
 
@@ -561,6 +567,7 @@ public class Navigator implements Serializable {
             }
             if (!navigationState.equals(getStateManager().getState())) {
                 getStateManager().setState(navigationState);
+                currentNavigationState = navigationState;
             }
         }
 
diff --git a/uitest/src/com/vaadin/tests/navigator/NavigatorViewBlocksBackButtonAction.java b/uitest/src/com/vaadin/tests/navigator/NavigatorViewBlocksBackButtonAction.java
new file mode 100644 (file)
index 0000000..5c78a3f
--- /dev/null
@@ -0,0 +1,128 @@
+package com.vaadin.tests.navigator;
+
+import com.vaadin.navigator.Navigator;
+import com.vaadin.navigator.View;
+import com.vaadin.navigator.ViewChangeListener;
+import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+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.VerticalLayout;
+import com.vaadin.ui.Window;
+
+public class NavigatorViewBlocksBackButtonAction extends AbstractTestUI {
+
+    private Navigator navigator;
+
+    protected static final String LABEL_MAINVIEW_ID = "LABEL_MAINVIEW_ID";
+    protected static final String LABEL_PROMPTEDVIEW_ID = "LABEL_PROMPTEDVIEW_ID";
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        navigator = new Navigator(this, this);
+        navigator.addView(MainView.NAME, new MainView());
+        navigator.addView(ViewWithPromptedLeave.NAME,
+                new ViewWithPromptedLeave());
+        navigator.navigateTo(MainView.NAME);
+    }
+
+    class MainView extends VerticalLayout implements View {
+
+        public static final String NAME = "mainview";
+
+        public MainView() {
+            Label label = new Label("MainView content");
+            label.setId(LABEL_MAINVIEW_ID);
+            addComponent(label);
+
+            Button buttonNavToAnotherView = new Button(
+                    "Navigate to another view", new ClickListener() {
+
+                        @Override
+                        public void buttonClick(ClickEvent event) {
+                            navigator.navigateTo(ViewWithPromptedLeave.NAME);
+                        }
+                    });
+            addComponent(buttonNavToAnotherView);
+        }
+
+        @Override
+        public void enter(ViewChangeEvent event) {
+        }
+
+    }
+
+    class ViewWithPromptedLeave extends VerticalLayout implements View,
+            ViewChangeListener {
+
+        public static final String NAME = "prompted";
+
+        protected boolean okToLeave;
+
+        public ViewWithPromptedLeave() {
+            Label label = new Label("ViewWithPromptedLeave content");
+            label.setId(LABEL_PROMPTEDVIEW_ID);
+            addComponent(label);
+            addComponent(new Label(
+                    "Try to navigate back to first view with browser back button."));
+        }
+
+        @Override
+        public void enter(ViewChangeEvent event) {
+            event.getNavigator().addViewChangeListener(this);
+        }
+
+        @Override
+        public boolean beforeViewChange(final ViewChangeEvent event) {
+            if (okToLeave) {
+                okToLeave = false;
+                return true;
+            } else {
+                final Window confirmationWindow = new Window("Confirm");
+                confirmationWindow.setModal(true);
+                confirmationWindow.setClosable(true);
+
+                VerticalLayout confirmationWindowLayout = new VerticalLayout();
+                confirmationWindow.setContent(confirmationWindowLayout);
+                confirmationWindowLayout.setMargin(true);
+                confirmationWindowLayout.setSpacing(true);
+                confirmationWindowLayout.addComponent(new Label(
+                        "Really exit this view?"));
+                confirmationWindowLayout.addComponent(new Button("Yeah, sure!",
+                        new Button.ClickListener() {
+
+                            @Override
+                            public void buttonClick(ClickEvent buttonEvent) {
+                                okToLeave = true;
+                                getUI().removeWindow(confirmationWindow);
+                                event.getNavigator().navigateTo(
+                                        event.getViewName() + "/"
+                                                + event.getParameters());
+                            }
+                        }));
+                getUI().addWindow(confirmationWindow);
+                return false;
+            }
+        }
+
+        @Override
+        public void afterViewChange(ViewChangeEvent event) {
+            if (event.getNewView() != this) {
+                event.getNavigator().removeViewChangeListener(this);
+            }
+        }
+    }
+
+    @Override
+    protected String getTestDescription() {
+        return "URL should not be changed when view blocks navigating away from view using the browser's Back-button";
+    }
+
+    @Override
+    protected Integer getTicketNumber() {
+        return 10901;
+    }
+}
\ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/navigator/NavigatorViewBlocksBackButtonActionTest.java b/uitest/src/com/vaadin/tests/navigator/NavigatorViewBlocksBackButtonActionTest.java
new file mode 100644 (file)
index 0000000..84abdca
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * 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.navigator;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class NavigatorViewBlocksBackButtonActionTest extends MultiBrowserTest {
+
+    @Test
+    public void testIfConfirmBack() {
+        openTestURL();
+
+        // keep URL of main view
+        final String initialUrl = driver.getCurrentUrl();
+
+        // do it 2 times to verify that login is not broken after first time
+        for (int i = 0; i < 2; i++) {
+            // go to prompted view
+            WebElement button = $(ButtonElement.class).first();
+            button.click();
+
+            // click back button
+            driver.navigate().back();
+
+            // confirm "go back by clicking confirm button
+            WebElement buttonConfirmView = $(ButtonElement.class).first();
+            buttonConfirmView.click();
+
+            // verify we are in main view and url is correct
+            waitForElementPresent(By
+                    .id(NavigatorViewBlocksBackButtonAction.LABEL_MAINVIEW_ID));
+            String currentUrl = driver.getCurrentUrl();
+            assertEquals(
+                    "Current URL should be equal to initial main view URL",
+                    initialUrl, currentUrl);
+        }
+    }
+
+    @Test
+    public void testIfCancelBack() {
+        openTestURL();
+
+        // go to prompted view
+        WebElement button = $(ButtonElement.class).first();
+        button.click();
+
+        // keep URL of prompted view
+        final String initialPromptedUrl = driver.getCurrentUrl();
+
+        // click back button
+        driver.navigate().back();
+
+        // verify url is correct (is not changed)
+        waitForElementPresent(By
+                .id(NavigatorViewBlocksBackButtonAction.LABEL_PROMPTEDVIEW_ID));
+        String currentUrl = driver.getCurrentUrl();
+        assertEquals(
+                "Current URL should be equal to initial prompted view URL",
+                initialPromptedUrl, currentUrl);
+
+        WebElement cancelButton = driver.findElement(By
+                .className("v-window-closebox"));
+
+        // click cancel button
+        cancelButton.click();
+
+        // verify we leave in prompted view and url is correct
+        waitForElementPresent(By
+                .id(NavigatorViewBlocksBackButtonAction.LABEL_PROMPTEDVIEW_ID));
+        currentUrl = driver.getCurrentUrl();
+        assertEquals(
+                "Current URL should be equal to initial prompted view URL",
+                initialPromptedUrl, currentUrl);
+    }
+}