diff options
author | Denis Anisimov <denis@vaadin.com> | 2014-10-05 13:29:25 +0300 |
---|---|---|
committer | Denis Anisimov <denis@vaadin.com> | 2015-11-07 10:47:23 +0200 |
commit | d18d2fb7edd7901bab603bbce02d561808300ab3 (patch) | |
tree | 1009e8d830e43ab9a45f1bfd6288417bde158d0f /server | |
parent | 9c1908d0a5fdba09167414e837cc08a2f746584b (diff) | |
download | vaadin-framework-d18d2fb7edd7901bab603bbce02d561808300ab3.tar.gz vaadin-framework-d18d2fb7edd7901bab603bbce02d561808300ab3.zip |
Add destroy method for Navigator (#10213).
Change-Id: Icb2676bd603bbe36a8d7d005128036234a5a0c62
Diffstat (limited to 'server')
4 files changed, 175 insertions, 6 deletions
diff --git a/server/src/com/vaadin/navigator/NavigationStateManager.java b/server/src/com/vaadin/navigator/NavigationStateManager.java index d454d044cb..3e9c54c961 100644 --- a/server/src/com/vaadin/navigator/NavigationStateManager.java +++ b/server/src/com/vaadin/navigator/NavigationStateManager.java @@ -56,6 +56,8 @@ public interface NavigationStateManager extends Serializable { * Sets the Navigator used with this state manager. The state manager should * notify the provided navigator of user-triggered navigation state changes * by invoking <code>navigator.navigateTo(getState())</code>. + * {@code navigator} parameter value could be null if previously set + * navigator is destroyed. * <p> * This method should only be called by a Navigator. */ diff --git a/server/src/com/vaadin/navigator/Navigator.java b/server/src/com/vaadin/navigator/Navigator.java index fa587a2eaa..82e8de920a 100644 --- a/server/src/com/vaadin/navigator/Navigator.java +++ b/server/src/com/vaadin/navigator/Navigator.java @@ -113,11 +113,15 @@ public class Navigator implements Serializable { */ public UriFragmentManager(Page page) { this.page = page; - page.addUriFragmentChangedListener(this); } @Override public void setNavigator(Navigator navigator) { + if (this.navigator == null && navigator != null) { + page.addUriFragmentChangedListener(this); + } else if (this.navigator != null && navigator == null) { + page.removeUriFragmentChangedListener(this); + } this.navigator = navigator; } @@ -980,4 +984,13 @@ public class Navigator implements Serializable { public void removeViewChangeListener(ViewChangeListener listener) { listeners.remove(listener); } + + /** + * Destroys the navigator and cleans it up. The method detaches the + * navigator from UI and removes all view change listeners. + */ + public void destroy() { + stateManager.setNavigator(null); + ui.setNavigator(null); + } } diff --git a/server/tests/src/com/vaadin/tests/server/navigator/NavigatorTest.java b/server/tests/src/com/vaadin/tests/server/navigator/NavigatorTest.java index 2c045d53fa..0de804fa0b 100644 --- a/server/tests/src/com/vaadin/tests/server/navigator/NavigatorTest.java +++ b/server/tests/src/com/vaadin/tests/server/navigator/NavigatorTest.java @@ -23,14 +23,19 @@ import junit.framework.TestCase; import org.easymock.EasyMock; import org.easymock.IArgumentMatcher; import org.easymock.IMocksControl; +import org.junit.Assert; import com.vaadin.navigator.NavigationStateManager; import com.vaadin.navigator.Navigator; +import com.vaadin.navigator.Navigator.UriFragmentManager; import com.vaadin.navigator.View; import com.vaadin.navigator.ViewChangeListener; import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; import com.vaadin.navigator.ViewDisplay; import com.vaadin.navigator.ViewProvider; +import com.vaadin.server.Page; +import com.vaadin.server.Page.UriFragmentChangedEvent; +import com.vaadin.server.VaadinRequest; import com.vaadin.tests.server.navigator.ClassBasedViewProviderTest.TestView; import com.vaadin.tests.server.navigator.ClassBasedViewProviderTest.TestView2; import com.vaadin.ui.Component; @@ -84,6 +89,10 @@ public class NavigatorTest extends TestCase { super(createMockUI(), new NullFragmentManager(), new TestDisplay()); } + public TestNavigator(UI ui) { + super(ui, EasyMock.createMock(ViewDisplay.class)); + } + public View getView(String viewAndParameters) { try { navigateTo(viewAndParameters); @@ -92,6 +101,11 @@ public class NavigatorTest extends TestCase { } return ((TestDisplay) getDisplay()).getCurrentView(); } + + @Override + protected NavigationStateManager getStateManager() { + return super.getStateManager(); + } } public static class ViewChangeTestListener implements ViewChangeListener { @@ -181,6 +195,55 @@ public class NavigatorTest extends TestCase { } } + private static class TestUI extends UI { + + TestUI(Page page) { + this.page = page; + } + + @Override + protected void init(VaadinRequest request) { + } + + @Override + public Page getPage() { + return page; + } + + private Page page; + } + + private static class TestPage extends Page { + + public TestPage() { + super(null, null); + } + + @Override + public void addUriFragmentChangedListener( + UriFragmentChangedListener listener) { + addUriFragmentCalled = true; + } + + @Override + public void removeUriFragmentChangedListener( + UriFragmentChangedListener listener) { + removeUriFragmentCalled = true; + } + + boolean addUriFragmentCalled() { + return addUriFragmentCalled; + } + + boolean removeUriFragmentCalled() { + return removeUriFragmentCalled; + } + + private boolean addUriFragmentCalled; + + private boolean removeUriFragmentCalled; + } + public static ViewChangeEvent eventParametersEqual(final String expected) { EasyMock.reportMatcher(new IArgumentMatcher() { @Override @@ -210,6 +273,35 @@ public class NavigatorTest extends TestCase { return new Navigator(createMockUI(), manager, display); } + public void testDestroy_unsetNavigatorInUIAndUriFragmentManager() { + TestPage page = new TestPage(); + UI ui = new TestUI(page); + + TestNavigator navigator = new TestNavigator(ui); + Assert.assertTrue("Add URI fragment Page method has not been called", + page.addUriFragmentCalled()); + Assert.assertFalse("Unexpected remove URI fragment Page method call", + page.removeUriFragmentCalled()); + Assert.assertNotNull("Navigator is null in UI", ui.getNavigator()); + + navigator.destroy(); + Assert.assertTrue( + "Remove URI fragment Page method has not been called after destroy", + page.removeUriFragmentCalled()); + Assert.assertNull("Navigator is not null in UI after destroy", + ui.getNavigator()); + UriFragmentManager manager = (UriFragmentManager) navigator + .getStateManager(); + try { + manager.uriFragmentChanged(EasyMock + .createMock(UriFragmentChangedEvent.class)); + Assert.assertTrue( + "Expected null pointer exception after call uriFragmentChanged " + + "for destroyed navigator", false); + } catch (NullPointerException e) { + } + } + public void testBasicNavigation() { IMocksControl control = EasyMock.createControl(); NavigationStateManager manager = control diff --git a/server/tests/src/com/vaadin/tests/server/navigator/UriFragmentManagerTest.java b/server/tests/src/com/vaadin/tests/server/navigator/UriFragmentManagerTest.java index 85de106e23..327baae21f 100644 --- a/server/tests/src/com/vaadin/tests/server/navigator/UriFragmentManagerTest.java +++ b/server/tests/src/com/vaadin/tests/server/navigator/UriFragmentManagerTest.java @@ -16,18 +16,19 @@ package com.vaadin.tests.server.navigator; -import junit.framework.TestCase; - import org.easymock.EasyMock; import org.easymock.IMocksControl; +import org.junit.Assert; +import org.junit.Test; import com.vaadin.navigator.Navigator; import com.vaadin.navigator.Navigator.UriFragmentManager; import com.vaadin.server.Page; import com.vaadin.server.Page.UriFragmentChangedEvent; -public class UriFragmentManagerTest extends TestCase { +public class UriFragmentManagerTest { + @Test public void testGetSetUriFragment() { Page page = EasyMock.createMock(Page.class); UriFragmentManager manager = new UriFragmentManager(page); @@ -39,11 +40,13 @@ public class UriFragmentManagerTest extends TestCase { EasyMock.replay(page); // test manager using the mock - assertEquals("Incorrect fragment value", "", manager.getState()); + Assert.assertEquals("Incorrect fragment value", "", manager.getState()); manager.setState("test"); - assertEquals("Incorrect fragment value", "test", manager.getState()); + Assert.assertEquals("Incorrect fragment value", "test", + manager.getState()); } + @Test public void testListener() { // create mocks IMocksControl control = EasyMock.createControl(); @@ -61,4 +64,63 @@ public class UriFragmentManagerTest extends TestCase { "oldtest"); manager.uriFragmentChanged(event); } + + @Test + public void setNavigator_someNavigatorInstance_uriFragmentChangedListenerIsRemoved() { + TestPage page = new TestPage(); + + UriFragmentManager manager = new UriFragmentManager(page); + manager.setNavigator(EasyMock.createMock(Navigator.class)); + + Assert.assertTrue( + "addUriFragmentChangedListener() method is not called for the Page", + page.addUriFragmentCalled()); + Assert.assertFalse( + "removeUriFragmentChangedListener() method is called for the Page", + page.removeUriFragmentCalled()); + } + + @Test + public void setNavigator_nullNavigatorInstance_uriFragmentChangedListenerIsRemoved() { + TestPage page = new TestPage(); + + UriFragmentManager manager = new UriFragmentManager(page); + manager.setNavigator(EasyMock.createMock(Navigator.class)); + + manager.setNavigator(null); + Assert.assertTrue( + "removeUriFragmentChangedListener() method is not called for the Page", + page.removeUriFragmentCalled()); + } + + private static class TestPage extends Page { + + public TestPage() { + super(null, null); + } + + @Override + public void addUriFragmentChangedListener( + UriFragmentChangedListener listener) { + addUriFragmentCalled = true; + } + + @Override + public void removeUriFragmentChangedListener( + UriFragmentChangedListener listener) { + removeUriFragmentCalled = true; + } + + boolean addUriFragmentCalled() { + return addUriFragmentCalled; + } + + boolean removeUriFragmentCalled() { + return removeUriFragmentCalled; + } + + private boolean addUriFragmentCalled; + + private boolean removeUriFragmentCalled; + } } |