/* * Copyright 2015 Red Hat, Inc. and/or its affiliates. * * 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 org.uberfire.client.workbench.panels.impl; import java.lang.annotation.Annotation; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import javax.enterprise.context.Dependent; import javax.enterprise.event.Event; import com.google.gwt.event.shared.EventBus; import com.google.gwt.user.client.ui.HasWidgets; import org.jboss.errai.common.client.dom.HTMLElement; import org.jboss.errai.ioc.client.QualifierUtil; import org.jboss.errai.ioc.client.container.IOC; import org.jboss.errai.ioc.client.container.SyncBeanManagerImpl; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InOrder; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; import org.mockito.stubbing.Answer; import org.uberfire.backend.vfs.ObservablePath; import org.uberfire.backend.vfs.Path; import org.uberfire.client.mvp.AbstractPopupActivity; import org.uberfire.client.mvp.Activity; import org.uberfire.client.mvp.ActivityManager; import org.uberfire.client.mvp.ContextActivity; import org.uberfire.client.mvp.PerspectiveActivity; import org.uberfire.client.mvp.PerspectiveManager; import org.uberfire.client.mvp.PlaceHistoryHandler; import org.uberfire.client.mvp.PlaceManager; import org.uberfire.client.mvp.PlaceManagerImpl; import org.uberfire.client.mvp.PlaceStatus; import org.uberfire.client.mvp.SplashScreenActivity; import org.uberfire.client.mvp.UIPart; import org.uberfire.client.mvp.WorkbenchActivity; import org.uberfire.client.mvp.WorkbenchScreenActivity; import org.uberfire.client.util.MockIOCBeanDef; import org.uberfire.client.workbench.LayoutSelection; import org.uberfire.client.workbench.PanelManager; import org.uberfire.client.workbench.WorkbenchLayout; import org.uberfire.client.workbench.events.BeforeClosePlaceEvent; import org.uberfire.client.workbench.events.ClosePlaceEvent; import org.uberfire.client.workbench.events.NewSplashScreenActiveEvent; import org.uberfire.client.workbench.events.PlaceLostFocusEvent; import org.uberfire.client.workbench.events.SelectPlaceEvent; import org.uberfire.mvp.Command; import org.uberfire.mvp.ParameterizedCommand; import org.uberfire.mvp.PlaceRequest; import org.uberfire.mvp.impl.ConditionalPlaceRequest; import org.uberfire.mvp.impl.DefaultPlaceRequest; import org.uberfire.mvp.impl.PathPlaceRequest; import org.uberfire.workbench.model.ActivityResourceType; import org.uberfire.workbench.model.PanelDefinition; import org.uberfire.workbench.model.PerspectiveDefinition; import org.uberfire.workbench.model.Position; import org.uberfire.workbench.model.impl.PanelDefinitionImpl; import org.uberfire.workbench.model.impl.PartDefinitionImpl; import org.uberfire.workbench.model.impl.PerspectiveDefinitionImpl; import org.uberfire.workbench.model.menu.Menus; import org.uberfire.workbench.type.ResourceTypeDefinition; import static java.util.Collections.singleton; import static org.junit.Assert.*; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isNull; import static org.mockito.Matchers.refEq; import static org.mockito.Mockito.*; @RunWith(MockitoJUnitRunner.class) public class PlaceManagerTest { /** * Returned by the mock activityManager for the special "workbench.activity.notfound" place. */ private final Activity notFoundActivity = mock(Activity.class); /** * The setup method makes this the current place. */ private final PlaceRequest kansas = new DefaultPlaceRequest("kansas"); /** * The setup method links this activity with the kansas PlaceRequest. */ private final WorkbenchScreenActivity kansasActivity = mock(WorkbenchScreenActivity.class); /** * This panel will always be returned from panelManager.getRoot(). */ private final PanelDefinition rootPanel = new PanelDefinitionImpl( MultiListWorkbenchPanelPresenter.class.getName()); @Mock Event<BeforeClosePlaceEvent> workbenchPartBeforeCloseEvent; @Mock Event<ClosePlaceEvent> workbenchPartCloseEvent; @Mock Event<PlaceLostFocusEvent> workbenchPartLostFocusEvent; @Mock Event<NewSplashScreenActiveEvent> newSplashScreenActiveEvent; @Mock ActivityManager activityManager; @Mock PlaceHistoryHandler placeHistoryHandler; @Mock Event<SelectPlaceEvent> selectWorkbenchPartEvent; @Mock PanelManager panelManager; @Mock PerspectiveManager perspectiveManager; @Mock WorkbenchLayout workbenchLayout; @Mock LayoutSelection layoutSelection; /** * This is the thing we're testing. Weeee! */ @InjectMocks PlaceManagerImpl placeManager; @Before public void setup() { ((SyncBeanManagerImpl) IOC.getBeanManager()).reset(); when(activityManager.getActivities(any(PlaceRequest.class))).thenReturn(singleton(notFoundActivity)); // for now (and this will have to change for UF-61), PathPlaceRequest performs an IOC lookup for ObservablePath in its constructor // as part of UF-61, we'll need to refactor ObservablePath and PathFactory so they ask for any beans they need as constructor params. final ObservablePath mockObservablePath = mock(ObservablePath.class); when(mockObservablePath.wrap(any(Path.class))).thenReturn(mockObservablePath); IOC.getBeanManager().registerBean(new MockIOCBeanDef<ObservablePath, ObservablePath>(mockObservablePath, ObservablePath.class, Dependent.class, new HashSet<Annotation>( Arrays.asList( QualifierUtil.DEFAULT_QUALIFIERS)), "ObservablePath", true)); // every test starts in Kansas, with no side effect interactions recorded when(activityManager.getActivities(kansas)).thenReturn(singleton((Activity) kansasActivity)); setupPanelManagerMock(); when(kansasActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); when(kansasActivity.isDynamic()).thenReturn(false); placeManager.goTo(kansas, (PanelDefinition) null); resetInjectedMocks(); reset(kansasActivity); when(kansasActivity.onMayClose()).thenReturn(true); when(kansasActivity.preferredWidth()).thenReturn(123); when(kansasActivity.preferredHeight()).thenReturn(456); // arrange for the mock PerspectiveManager to invoke the doWhenFinished callbacks doAnswer(new Answer<Void>() { @SuppressWarnings({"rawtypes", "unchecked"}) @Override public Void answer(InvocationOnMock invocation) throws Throwable { ParameterizedCommand callback = (ParameterizedCommand) invocation.getArguments()[2]; PerspectiveActivity perspectiveActivity = (PerspectiveActivity) invocation.getArguments()[1]; callback.execute(perspectiveActivity.getDefaultPerspectiveLayout()); return null; } }).when(perspectiveManager).switchToPerspective(any(PlaceRequest.class), any(PerspectiveActivity.class), any(ParameterizedCommand.class)); doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { Command callback = (Command) invocation.getArguments()[0]; callback.execute(); return null; } }).when(perspectiveManager).savePerspectiveState(any(Command.class)); } /** * Resets all the mocks that were injected into the PlaceManager under test. This should probably only be used in * the setup method. */ @SuppressWarnings("unchecked") private void resetInjectedMocks() { reset(workbenchPartBeforeCloseEvent); reset(workbenchPartCloseEvent); reset(workbenchPartLostFocusEvent); reset(newSplashScreenActiveEvent); reset(activityManager); reset(placeHistoryHandler); reset(selectWorkbenchPartEvent); reset(panelManager); reset(perspectiveManager); reset(workbenchLayout); setupPanelManagerMock(); } private void setupPanelManagerMock() { when(panelManager.getRoot()).thenReturn(rootPanel); when(panelManager.addWorkbenchPanel(any(PanelDefinition.class), any(Position.class), any(Integer.class), any(Integer.class), any(Integer.class), any(Integer.class))) .thenAnswer(new Answer<PanelDefinition>() { @Override public PanelDefinition answer(InvocationOnMock invocation) throws Throwable { return (PanelDefinition) invocation.getArguments()[0]; } }); } @Test public void testPlaceManagerGetsInitializedToADefaultPlace() throws Exception { placeManager.initPlaceHistoryHandler(); verify(placeHistoryHandler).register(any(PlaceManager.class), any(EventBus.class), any(PlaceRequest.class)); } @Test public void testGoToConditionalPlaceById() throws Exception { PlaceRequest dora = new ConditionalPlaceRequest("dora").when(p -> true) .orElse(new DefaultPlaceRequest("other")); WorkbenchScreenActivity doraActivity = mock(WorkbenchScreenActivity.class); when(doraActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); when(activityManager.getActivities(dora)).thenReturn(singleton((Activity) doraActivity)); placeManager.goTo(dora); verifyActivityLaunchSideEffects(dora, doraActivity, null); } @Test public void testGoToConditionalPlaceByIdOrElse() throws Exception { DefaultPlaceRequest other = new DefaultPlaceRequest("other"); PlaceRequest dora = new ConditionalPlaceRequest("dora").when(p -> false) .orElse(other); WorkbenchScreenActivity doraActivity = mock(WorkbenchScreenActivity.class); WorkbenchScreenActivity otherActivity = mock(WorkbenchScreenActivity.class); when(doraActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); when(otherActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); when(activityManager.getActivities(dora)).thenReturn(singleton((Activity) doraActivity)); when(activityManager.getActivities(other)).thenReturn(singleton((Activity) otherActivity)); placeManager.goTo(dora); verify(doraActivity, never()).onOpen(); verify(otherActivity).onOpen(); verifyActivityLaunchSideEffects(other, otherActivity, null); } @Test public void testGoToNewPlaceById() throws Exception { PlaceRequest oz = new DefaultPlaceRequest("oz"); WorkbenchScreenActivity ozActivity = mock(WorkbenchScreenActivity.class); when(ozActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); when(ozActivity.isDynamic()).thenReturn(false); when(ozActivity.preferredWidth()).thenReturn(-1); when(ozActivity.preferredHeight()).thenReturn(-1); when(activityManager.getActivities(oz)).thenReturn(singleton((Activity) ozActivity)); placeManager.goTo(oz, (PanelDefinition) null); verifyActivityLaunchSideEffects(oz, ozActivity, null); } @Test public void testGoToPlaceWeAreAlreadyAt() throws Exception { when(kansasActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); placeManager.goTo(kansas, (PanelDefinition) null); // note "refEq" tests equality field by field using reflection. don't read it as "reference equals!" :) verify(selectWorkbenchPartEvent).fire(refEq(new SelectPlaceEvent(kansas))); verifyNoActivityLaunchSideEffects(kansas, kansasActivity); } @Test public void testGoToPartWeAreAlreadyAt() throws Exception { when(kansasActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); placeManager.goTo(new PartDefinitionImpl(kansas), null); // note "refEq" tests equality field by field using reflection. don't read it as "reference equals!" :) verify(selectWorkbenchPartEvent).fire(refEq(new SelectPlaceEvent(kansas))); verifyNoActivityLaunchSideEffects(kansas, kansasActivity); } @Test public void testGoToNowhereDoesNothing() throws Exception { placeManager.goTo(PlaceRequest.NOWHERE, (PanelDefinition) null); verifyNoActivityLaunchSideEffects(kansas, kansasActivity); } // XXX would like to remove this behaviour (should throw NPE) but too many things are up in the air right now @Test public void testGoToNullDoesNothing() throws Exception { placeManager.goTo((PlaceRequest) null, (PanelDefinition) null); verifyNoActivityLaunchSideEffects(kansas, kansasActivity); } @Test public void testGoToPlaceByPath() throws Exception { PathPlaceRequest yellowBrickRoad = new FakePathPlaceRequest(mock(ObservablePath.class)); WorkbenchScreenActivity ozActivity = mock(WorkbenchScreenActivity.class); when(ozActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); when(activityManager.getActivities(yellowBrickRoad)).thenReturn(singleton((Activity) ozActivity)); placeManager.goTo(yellowBrickRoad, (PanelDefinition) null); verifyActivityLaunchSideEffects(yellowBrickRoad, ozActivity, null); // special contract just for path-type place requests (subject to preference) verify(yellowBrickRoad.getPath(), never()).onDelete(any(Command.class)); } @Test public void testNormalCloseExistingScreenActivity() throws Exception { when(kansasActivity.onMayClose()).thenReturn(true); when(kansasActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); placeManager.closePlace(kansas); verify(workbenchPartBeforeCloseEvent).fire(refEq(new BeforeClosePlaceEvent(kansas, false, true))); verify(workbenchPartCloseEvent).fire(refEq(new ClosePlaceEvent(kansas))); verify(kansasActivity).onMayClose(); verify(kansasActivity).onClose(); verify(kansasActivity, never()).onShutdown(); verify(activityManager).destroyActivity(kansasActivity); verify(panelManager).removePartForPlace(kansas); assertEquals(PlaceStatus.CLOSE, placeManager.getStatus(kansas)); assertNull(placeManager.getActivity(kansas)); assertFalse(placeManager.getActivePlaceRequests().contains(kansas)); } @Test public void testCanceledCloseExistingScreenActivity() throws Exception { when(kansasActivity.onMayClose()).thenReturn(false); when(kansasActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); placeManager.closePlace(kansas); verify(workbenchPartBeforeCloseEvent).fire(refEq(new BeforeClosePlaceEvent(kansas, false, true))); verify(workbenchPartCloseEvent, never()).fire(refEq(new ClosePlaceEvent(kansas))); verify(kansasActivity).onMayClose(); verify(kansasActivity, never()).onClose(); verify(kansasActivity, never()).onShutdown(); verify(activityManager, never()).destroyActivity(kansasActivity); verify(panelManager, never()).removePartForPlace(kansas); assertEquals(PlaceStatus.OPEN, placeManager.getStatus(kansas)); assertSame(kansasActivity, placeManager.getActivity(kansas)); assertTrue(placeManager.getActivePlaceRequests().contains(kansas)); } @Test public void testForceCloseExistingScreenActivity() throws Exception { when(kansasActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); placeManager.forceClosePlace(kansas); verify(workbenchPartBeforeCloseEvent).fire(refEq(new BeforeClosePlaceEvent(kansas, true, true))); verify(workbenchPartCloseEvent).fire(refEq(new ClosePlaceEvent(kansas))); verify(kansasActivity, never()).onMayClose(); verify(kansasActivity).onClose(); verify(kansasActivity, never()).onShutdown(); verify(activityManager).destroyActivity(kansasActivity); verify(panelManager).removePartForPlace(kansas); assertEquals(PlaceStatus.CLOSE, placeManager.getStatus(kansas)); assertNull(placeManager.getActivity(kansas)); assertFalse(placeManager.getActivePlaceRequests().contains(kansas)); } /** * Tests the basics of launching a perspective. We call it "empty" because this perspective doesn't have any panels * or parts in its definition. */ @Test public void testLaunchingEmptyPerspective() throws Exception { PerspectiveActivity ozPerspectiveActivity = mock(PerspectiveActivity.class); PlaceRequest ozPerspectivePlace = new DefaultPlaceRequest("oz_perspective"); PerspectiveDefinition ozPerspectiveDef = new PerspectiveDefinitionImpl(); when(activityManager.getActivities(ozPerspectivePlace)) .thenReturn(singleton((Activity) ozPerspectiveActivity)); when(ozPerspectiveActivity.getDefaultPerspectiveLayout()).thenReturn(ozPerspectiveDef); when(ozPerspectiveActivity.getPlace()).thenReturn(ozPerspectivePlace); when(ozPerspectiveActivity.isType(ActivityResourceType.PERSPECTIVE.name())).thenReturn(true); placeManager.goTo(ozPerspectivePlace); // verify perspective changed to oz verify(perspectiveManager).savePerspectiveState(any(Command.class)); verify(perspectiveManager).switchToPerspective(any(PlaceRequest.class), eq(ozPerspectiveActivity), any(ParameterizedCommand.class)); verify(ozPerspectiveActivity).onOpen(); assertEquals(PlaceStatus.OPEN, placeManager.getStatus(ozPerspectivePlace)); assertTrue(placeManager.getActivePlaceRequests().contains(ozPerspectivePlace)); assertEquals(ozPerspectiveActivity, placeManager.getActivity(ozPerspectivePlace)); verify(workbenchLayout).onResize(); } @Test public void testSwitchingPerspectives() throws Exception { PerspectiveActivity ozPerspectiveActivity = mock(PerspectiveActivity.class); PlaceRequest ozPerspectivePlace = new DefaultPlaceRequest("oz_perspective"); PerspectiveDefinition ozPerspectiveDef = new PerspectiveDefinitionImpl(); when(activityManager.getActivities(ozPerspectivePlace)) .thenReturn(singleton((Activity) ozPerspectiveActivity)); when(ozPerspectiveActivity.getDefaultPerspectiveLayout()).thenReturn(ozPerspectiveDef); when(ozPerspectiveActivity.getPlace()).thenReturn(ozPerspectivePlace); when(ozPerspectiveActivity.isType(ActivityResourceType.PERSPECTIVE.name())).thenReturn(true); when(kansasActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); // we'll pretend we started in kansas PerspectiveActivity kansasPerspectiveActivity = mock(PerspectiveActivity.class); when(perspectiveManager.getCurrentPerspective()).thenReturn(kansasPerspectiveActivity); placeManager.goTo(ozPerspectivePlace); // verify proper shutdown of kansasPerspective and its contents InOrder inOrder = inOrder(activityManager, kansasPerspectiveActivity, kansasActivity, workbenchLayout); // shut down the screens first inOrder.verify(kansasActivity).onClose(); inOrder.verify(activityManager).destroyActivity(kansasActivity); // then the perspective inOrder.verify(kansasPerspectiveActivity).onClose(); inOrder.verify(activityManager).destroyActivity(kansasPerspectiveActivity); inOrder.verify(workbenchLayout).onResize(); } @Test public void testSwitchingFromPerspectiveToSelf() throws Exception { PerspectiveActivity ozPerspectiveActivity = mock(PerspectiveActivity.class); PlaceRequest ozPerspectivePlace = new DefaultPlaceRequest("oz_perspective"); PerspectiveDefinition ozPerspectiveDef = new PerspectiveDefinitionImpl(); when(activityManager.getActivities(ozPerspectivePlace)) .thenReturn(singleton((Activity) ozPerspectiveActivity)); when(ozPerspectiveActivity.getDefaultPerspectiveLayout()).thenReturn(ozPerspectiveDef); when(ozPerspectiveActivity.getPlace()).thenReturn(ozPerspectivePlace); // we'll pretend we started in oz when(perspectiveManager.getCurrentPerspective()).thenReturn(ozPerspectiveActivity); placeManager.goTo(ozPerspectivePlace); // verify no side effects (should stay put) verify(ozPerspectiveActivity, never()).onOpen(); verify(perspectiveManager, never()).savePerspectiveState(any(Command.class)); verify(perspectiveManager, never()) .switchToPerspective(any(PlaceRequest.class), any(PerspectiveActivity.class), any(ParameterizedCommand.class)); } /** * This test verifies that when launching a screen which is "owned by" a perspective other than the current one, the * PlaceManager first switches to the owning perspective and then launches the requested screen. */ @Test public void testLaunchingActivityTiedToDifferentPerspective() throws Exception { PerspectiveActivity ozPerspectiveActivity = mock(PerspectiveActivity.class); PlaceRequest ozPerspectivePlace = new DefaultPlaceRequest("oz_perspective"); PerspectiveDefinition ozPerspectiveDef = new PerspectiveDefinitionImpl(); when(activityManager.getActivities(ozPerspectivePlace)) .thenReturn(singleton((Activity) ozPerspectiveActivity)); when(ozPerspectiveActivity.getDefaultPerspectiveLayout()).thenReturn(ozPerspectiveDef); when(ozPerspectiveActivity.getPlace()).thenReturn(ozPerspectivePlace); when(ozPerspectiveActivity.isType(ActivityResourceType.PERSPECTIVE.name())).thenReturn(true); PlaceRequest emeraldCityPlace = new DefaultPlaceRequest("emerald_city"); WorkbenchScreenActivity emeraldCityActivity = mock(WorkbenchScreenActivity.class); when(activityManager.getActivities(emeraldCityPlace)) .thenReturn(singleton((Activity) emeraldCityActivity)); when(emeraldCityActivity.getOwningPlace()).thenReturn(ozPerspectivePlace); when(emeraldCityActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); placeManager.goTo(emeraldCityPlace, (PanelDefinition) null); // verify perspective changed to oz verify(perspectiveManager).savePerspectiveState(any(Command.class)); verify(perspectiveManager).switchToPerspective(any(PlaceRequest.class), eq(ozPerspectiveActivity), any(ParameterizedCommand.class)); assertEquals(PlaceStatus.OPEN, placeManager.getStatus(ozPerspectivePlace)); // verify perspective opened before the activity that launches inside it InOrder inOrder = inOrder(ozPerspectiveActivity, emeraldCityActivity); inOrder.verify(ozPerspectiveActivity).onOpen(); inOrder.verify(emeraldCityActivity).onOpen(); // and the workbench activity should have launched (after the perspective change) verifyActivityLaunchSideEffects(emeraldCityPlace, emeraldCityActivity, null); } @Test public void testPerspectiveLaunchWithSplashScreen() throws Exception { final PlaceRequest perspectivePlace = new DefaultPlaceRequest("Somewhere"); final PerspectiveActivity perspectiveActivity = mock(PerspectiveActivity.class); final PerspectiveDefinition perspectiveDef = new PerspectiveDefinitionImpl( SimpleWorkbenchPanelPresenter.class.getName()); when(perspectiveActivity.getDefaultPerspectiveLayout()).thenReturn(perspectiveDef); when(activityManager.getActivities(perspectivePlace)) .thenReturn(singleton((Activity) perspectiveActivity)); final SplashScreenActivity splashScreenActivity = mock(SplashScreenActivity.class); when(activityManager.getSplashScreenInterceptor(perspectivePlace)).thenReturn(splashScreenActivity); when(perspectiveActivity.isType(ActivityResourceType.PERSPECTIVE.name())).thenReturn(true); when(splashScreenActivity.isType(ActivityResourceType.SPLASH.name())).thenReturn(true); placeManager.goTo(perspectivePlace); // splash screen should be open and registered as an active splash screen verify(splashScreenActivity, never()).onStartup(any(PlaceRequest.class)); InOrder inOrder = inOrder(splashScreenActivity, newSplashScreenActiveEvent); inOrder.verify(splashScreenActivity).onOpen(); inOrder.verify(newSplashScreenActiveEvent).fire(any(NewSplashScreenActiveEvent.class)); assertTrue(placeManager.getActiveSplashScreens().contains(splashScreenActivity)); // perspective should be open, and should be the activity registered for its own place verify(perspectiveActivity, never()).onStartup(any(PlaceRequest.class)); verify(perspectiveActivity).onOpen(); assertEquals(PlaceStatus.OPEN, placeManager.getStatus(perspectivePlace)); assertSame(perspectiveActivity, placeManager.getActivity(perspectivePlace)); } @Test public void testProperSplashScreenShutdownOnPerspectiveSwitch() throws Exception { final PlaceRequest perspectivePlace = new DefaultPlaceRequest("Somewhere"); final PerspectiveActivity perspectiveActivity = mock(PerspectiveActivity.class); final PerspectiveDefinition perspectiveDef = new PerspectiveDefinitionImpl( SimpleWorkbenchPanelPresenter.class.getName()); when(perspectiveActivity.getDefaultPerspectiveLayout()).thenReturn(perspectiveDef); when(perspectiveActivity.isType(ActivityResourceType.PERSPECTIVE.name())).thenReturn(true); when(activityManager.getActivities(perspectivePlace)) .thenReturn(singleton((Activity) perspectiveActivity)); // first splash screen: linked to the perspective itself final SplashScreenActivity splashScreenActivity1 = mock(SplashScreenActivity.class); when(activityManager.getSplashScreenInterceptor(perspectivePlace)).thenReturn(splashScreenActivity1); when(splashScreenActivity1.isType(ActivityResourceType.SPLASH.name())).thenReturn(true); // second splash screen: linked to a screen that we will display in the perspective final SplashScreenActivity splashScreenActivity2 = mock(SplashScreenActivity.class); when(activityManager.getSplashScreenInterceptor(kansas)).thenReturn(splashScreenActivity2); when(activityManager.getActivities(kansas)).thenReturn(singleton((Activity) kansasActivity)); when(splashScreenActivity2.isType(ActivityResourceType.SPLASH.name())).thenReturn(true); when(kansasActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); placeManager.goTo(perspectivePlace); placeManager.goTo(kansas); assertTrue(placeManager.getActiveSplashScreens().contains(splashScreenActivity1)); assertTrue(placeManager.getActiveSplashScreens().contains(splashScreenActivity2)); // now switch to another perspective and ensure both kinds of splash screens got closed final PlaceRequest otherPerspectivePlace = new DefaultPlaceRequest("Elsewhere"); final PerspectiveActivity otherPerspectiveActivity = mock(PerspectiveActivity.class); final PerspectiveDefinition otherPerspectiveDef = new PerspectiveDefinitionImpl( SimpleWorkbenchPanelPresenter.class.getName()); when(otherPerspectiveActivity.getDefaultPerspectiveLayout()).thenReturn(otherPerspectiveDef); when(otherPerspectiveActivity.isType(ActivityResourceType.PERSPECTIVE.name())).thenReturn(true); when(activityManager.getActivities(otherPerspectivePlace)) .thenReturn(singleton((Activity) otherPerspectiveActivity)); placeManager.goTo(otherPerspectivePlace); assertTrue(placeManager.getActiveSplashScreens().isEmpty()); verify(splashScreenActivity1).closeIfOpen(); verify(splashScreenActivity2).closeIfOpen(); // splash screens are Application Scoped, but we still "destroy" them (activity manager will call their onShutdown) verify(activityManager).destroyActivity(splashScreenActivity1); verify(activityManager).destroyActivity(splashScreenActivity2); } @Test public void testPartLaunchWithSplashScreen() throws Exception { PlaceRequest oz = new DefaultPlaceRequest("oz"); WorkbenchScreenActivity ozActivity = mock(WorkbenchScreenActivity.class); when(activityManager.getActivities(oz)).thenReturn(singleton((Activity) ozActivity)); when(ozActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); final SplashScreenActivity lollipopGuildActivity = mock(SplashScreenActivity.class); when(activityManager.getSplashScreenInterceptor(oz)).thenReturn(lollipopGuildActivity); when(lollipopGuildActivity.isType(ActivityResourceType.SPLASH.name())).thenReturn(true); placeManager.goTo(oz, (PanelDefinition) null); assertTrue(placeManager.getActiveSplashScreens().contains(lollipopGuildActivity)); verify(lollipopGuildActivity, never()).onStartup(any(PlaceRequest.class)); InOrder inOrder = inOrder(lollipopGuildActivity, newSplashScreenActiveEvent); inOrder.verify(lollipopGuildActivity).onOpen(); inOrder.verify(newSplashScreenActiveEvent).fire(any(NewSplashScreenActiveEvent.class)); } @Test public void testProperSplashScreenShutdownOnPartClose() throws Exception { PlaceRequest oz = new DefaultPlaceRequest("oz"); WorkbenchScreenActivity ozActivity = mock(WorkbenchScreenActivity.class); when(activityManager.getActivities(oz)).thenReturn(singleton((Activity) ozActivity)); final SplashScreenActivity lollipopGuildActivity = mock(SplashScreenActivity.class); when(lollipopGuildActivity.isType(ActivityResourceType.SPLASH.name())).thenReturn(true); when(activityManager.getSplashScreenInterceptor(oz)).thenReturn(lollipopGuildActivity); when(ozActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); placeManager.goTo(oz, (PanelDefinition) null); placeManager.closePlace(oz); assertTrue(placeManager.getActiveSplashScreens().isEmpty()); verify(lollipopGuildActivity).closeIfOpen(); // splash screens are Application Scoped, but we still "destroy" them (activity manager will call their onShutdown) verify(activityManager).destroyActivity(lollipopGuildActivity); } /** * Ensures that splash screens can't be launched on their own (they should only launch as a side effect of launching * a place that they intercept). This test came from the original test suite, and may not be all that relevant * anymore: it assumes that the ActivityManager might resolve a PlaceRequest to a SplashScreenActivity, and this is * currently not in the ActivityManager contract. */ @Test public void testSplashScreenActivityShouldNotLaunchOnItsOwn() throws Exception { final PlaceRequest somewhere = new DefaultPlaceRequest("Somewhere"); final SplashScreenActivity splashScreenActivity = mock(SplashScreenActivity.class); when(activityManager.getActivities(somewhere)).thenReturn(singleton((Activity) splashScreenActivity)); placeManager.goTo(somewhere); verify(splashScreenActivity, never()).onStartup(eq(somewhere)); verify(splashScreenActivity, never()).onOpen(); verify(newSplashScreenActiveEvent, never()).fire(any(NewSplashScreenActiveEvent.class)); assertFalse(placeManager.getActiveSplashScreens().contains(splashScreenActivity)); } /** * Ensures that context activities can't be launched on their own (they should only launch as a side effect of launching * a place that they relate to). This test was moved here from the original test suite. */ @Test public void testContextActivityShouldNotLaunchOnItsOwn() throws Exception { final PlaceRequest somewhere = new DefaultPlaceRequest("Somewhere"); final ContextActivity activity = mock(ContextActivity.class); when(activityManager.getActivities(somewhere)).thenReturn(singleton((Activity) activity)); placeManager.goTo(somewhere); verify(activity, never()).onStartup(eq(somewhere)); verify(activity, never()).onOpen(); } @Test public void testLaunchingPopup() throws Exception { final PlaceRequest popupPlace = new DefaultPlaceRequest("Somewhere"); final AbstractPopupActivity popupActivity = mock(AbstractPopupActivity.class); when(activityManager.getActivities(popupPlace)).thenReturn(singleton((Activity) popupActivity)); when(popupActivity.isType(ActivityResourceType.POPUP.name())).thenReturn(true); placeManager.goTo(popupPlace); verify(popupActivity, never()).onStartup(any(PlaceRequest.class)); verify(popupActivity, times(1)).onOpen(); verify(placeHistoryHandler, times(1)).onPlaceChange(popupPlace); assertEquals(PlaceStatus.OPEN, placeManager.getStatus(popupPlace)); // TODO this test was moved here from the old test suite. it may not verify all required side effects of launching a popup. } @Test public void testLaunchingPopupThatIsAlreadyOpen() throws Exception { final PlaceRequest popupPlace = new DefaultPlaceRequest("Somewhere"); final AbstractPopupActivity popupActivity = mock(AbstractPopupActivity.class); when(activityManager.getActivities(popupPlace)).thenReturn(singleton((Activity) popupActivity)); when(popupActivity.isType(ActivityResourceType.POPUP.name())).thenReturn(true); placeManager.goTo(popupPlace); placeManager.goTo(popupPlace); verify(popupActivity, never()).onStartup(any(PlaceRequest.class)); verify(popupActivity, times(1)).onOpen(); verify(placeHistoryHandler, times(1)).onPlaceChange(popupPlace); assertEquals(PlaceStatus.OPEN, placeManager.getStatus(popupPlace)); } @Test public void testReLaunchingClosedPopup() throws Exception { final PlaceRequest popupPlace = new DefaultPlaceRequest("Somewhere"); final AbstractPopupActivity popupActivity = mock(AbstractPopupActivity.class); when(popupActivity.onMayClose()).thenReturn(true); when(popupActivity.isType(ActivityResourceType.POPUP.name())).thenReturn(true); when(activityManager.getActivities(popupPlace)).thenReturn(singleton((Activity) popupActivity)); placeManager.goTo(popupPlace); placeManager.closePlace(popupPlace); placeManager.goTo(popupPlace); verify(popupActivity, times(2)).onOpen(); verify(popupActivity, times(1)).onClose(); assertEquals(PlaceStatus.OPEN, placeManager.getStatus(popupPlace)); } @Test public void testPopupCancelsClose() throws Exception { final PlaceRequest popupPlace = new DefaultPlaceRequest("Somewhere"); final AbstractPopupActivity popupActivity = mock(AbstractPopupActivity.class); when(popupActivity.onMayClose()).thenReturn(false); when(popupActivity.isType(ActivityResourceType.POPUP.name())).thenReturn(true); when(activityManager.getActivities(popupPlace)).thenReturn(singleton((Activity) popupActivity)); placeManager.goTo(popupPlace); placeManager.closePlace(popupPlace); verify(popupActivity, never()).onClose(); assertEquals(PlaceStatus.OPEN, placeManager.getStatus(popupPlace)); } @Test public void testLaunchActivityInCustomPanel() throws Exception { PanelDefinition customPanelDef = new PanelDefinitionImpl( UnanchoredStaticWorkbenchPanelPresenter.class.getName()); when(panelManager.addCustomPanel(any(HasWidgets.class), eq(UnanchoredStaticWorkbenchPanelPresenter.class.getName()))) .thenReturn(customPanelDef); PlaceRequest emeraldCityPlace = new DefaultPlaceRequest("emerald_city"); WorkbenchScreenActivity emeraldCityActivity = mock(WorkbenchScreenActivity.class); when(emeraldCityActivity.preferredWidth()).thenReturn(555); when(emeraldCityActivity.preferredHeight()).thenReturn(-1); when(activityManager.getActivities(emeraldCityPlace)) .thenReturn(singleton((Activity) emeraldCityActivity)); when(emeraldCityActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); HasWidgets customContainer = mock(HasWidgets.class); placeManager.goTo(emeraldCityPlace, customContainer); verifyActivityLaunchSideEffects(emeraldCityPlace, emeraldCityActivity, customPanelDef); verify(panelManager).addWorkbenchPart(eq(emeraldCityPlace), eq(new PartDefinitionImpl(emeraldCityPlace)), eq(customPanelDef), isNull(Menus.class), any(UIPart.class), isNull(String.class), isNull(Integer.class), isNull(Integer.class)); assertNull(customPanelDef.getParent()); } @Test public void testLaunchExistingActivityInCustomPanel() throws Exception { HasWidgets customContainer = mock(HasWidgets.class); when(kansasActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); placeManager.goTo(kansas, customContainer); verify(panelManager, never()) .addCustomPanel(customContainer, StaticWorkbenchPanelPresenter.class.getName()); verifyNoActivityLaunchSideEffects(kansas, kansasActivity); verify(selectWorkbenchPartEvent).fire(refEq(new SelectPlaceEvent(kansas))); } @Test public void testClosingActivityInCustomPanel() throws Exception { PanelDefinition customPanelDef = new PanelDefinitionImpl( UnanchoredStaticWorkbenchPanelPresenter.class.getName()); when(panelManager.addCustomPanel(any(HasWidgets.class), eq(UnanchoredStaticWorkbenchPanelPresenter.class.getName()))) .thenReturn(customPanelDef); PlaceRequest emeraldCityPlace = new DefaultPlaceRequest("emerald_city"); createWorkbenchScreenActivity(emeraldCityPlace); HasWidgets customContainer = mock(HasWidgets.class); placeManager.goTo(emeraldCityPlace, customContainer); placeManager.closePlace(emeraldCityPlace); assertTrue(customPanelDef.getParts().isEmpty()); verify(panelManager).removeWorkbenchPanel(customPanelDef); } @Test public void testClosingAllPlacesIncludesCustomPanels() throws Exception { PanelDefinition customPanelDef = new PanelDefinitionImpl( UnanchoredStaticWorkbenchPanelPresenter.class.getName()); when(panelManager.addCustomPanel(any(HasWidgets.class), eq(UnanchoredStaticWorkbenchPanelPresenter.class.getName()))) .thenReturn(customPanelDef); PlaceRequest emeraldCityPlace = new DefaultPlaceRequest("emerald_city"); createWorkbenchScreenActivity(emeraldCityPlace); HasWidgets customContainer = mock(HasWidgets.class); placeManager.goTo(emeraldCityPlace, customContainer); placeManager.closeAllPlaces(); assertTrue(customPanelDef.getParts().isEmpty()); verify(panelManager).removeWorkbenchPanel(customPanelDef); } @Test public void testLaunchActivityInCustomPanelInsideHTMLElement() throws Exception { PanelDefinition customPanelDef = new PanelDefinitionImpl( UnanchoredStaticWorkbenchPanelPresenter.class.getName()); when(panelManager.addCustomPanel(any(HTMLElement.class), eq(UnanchoredStaticWorkbenchPanelPresenter.class.getName()))) .thenReturn(customPanelDef); PlaceRequest emeraldCityPlace = new DefaultPlaceRequest("emerald_city"); WorkbenchScreenActivity emeraldCityActivity = mock(WorkbenchScreenActivity.class); when(emeraldCityActivity.preferredWidth()).thenReturn(555); when(emeraldCityActivity.preferredHeight()).thenReturn(-1); when(activityManager.getActivities(emeraldCityPlace)) .thenReturn(singleton((Activity) emeraldCityActivity)); when(emeraldCityActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); HTMLElement customContainer = mock(HTMLElement.class); placeManager.goTo(emeraldCityPlace, customContainer); verifyActivityLaunchSideEffects(emeraldCityPlace, emeraldCityActivity, customPanelDef); verify(panelManager).addWorkbenchPart(eq(emeraldCityPlace), eq(new PartDefinitionImpl(emeraldCityPlace)), eq(customPanelDef), isNull(Menus.class), any(UIPart.class), isNull(String.class), isNull(Integer.class), isNull(Integer.class)); assertNull(customPanelDef.getParent()); } @Test public void testLaunchExistingActivityInCustomPanelInsideHTMLElement() throws Exception { HTMLElement customContainer = mock(HTMLElement.class); when(kansasActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); placeManager.goTo(kansas, customContainer); verify(panelManager, never()) .addCustomPanel(customContainer, StaticWorkbenchPanelPresenter.class.getName()); verifyNoActivityLaunchSideEffects(kansas, kansasActivity); verify(selectWorkbenchPartEvent).fire(refEq(new SelectPlaceEvent(kansas))); } @Test public void testClosingActivityInCustomPanelInsideHTMLElement() throws Exception { PanelDefinition customPanelDef = new PanelDefinitionImpl( UnanchoredStaticWorkbenchPanelPresenter.class.getName()); when(panelManager.addCustomPanel(any(HTMLElement.class), eq(UnanchoredStaticWorkbenchPanelPresenter.class.getName()))) .thenReturn(customPanelDef); PlaceRequest emeraldCityPlace = new DefaultPlaceRequest("emerald_city"); createWorkbenchScreenActivity(emeraldCityPlace); HTMLElement customContainer = mock(HTMLElement.class); placeManager.goTo(emeraldCityPlace, customContainer); placeManager.closePlace(emeraldCityPlace); assertTrue(customPanelDef.getParts().isEmpty()); verify(panelManager).removeWorkbenchPanel(customPanelDef); } @Test public void testClosingAllPlacesIncludesCustomPanelsInsideHTMLElements() throws Exception { PanelDefinition customPanelDef = new PanelDefinitionImpl( UnanchoredStaticWorkbenchPanelPresenter.class.getName()); when(panelManager.addCustomPanel(any(HTMLElement.class), eq(UnanchoredStaticWorkbenchPanelPresenter.class.getName()))) .thenReturn(customPanelDef); PlaceRequest emeraldCityPlace = new DefaultPlaceRequest("emerald_city"); createWorkbenchScreenActivity(emeraldCityPlace); HTMLElement customContainer = mock(HTMLElement.class); placeManager.goTo(emeraldCityPlace, customContainer); placeManager.closeAllPlaces(); assertTrue(customPanelDef.getParts().isEmpty()); verify(panelManager).removeWorkbenchPanel(customPanelDef); } @Test public void testGetActivitiesForResourceType_NoMatches() throws Exception { final ObservablePath path = mock(ObservablePath.class); final PathPlaceRequest yellowBrickRoad = new FakePathPlaceRequest(path); final WorkbenchScreenActivity ozActivity = mock(WorkbenchScreenActivity.class); when(activityManager.getActivities(yellowBrickRoad)).thenReturn(singleton((Activity) ozActivity)); when(ozActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); placeManager.goTo(yellowBrickRoad); verifyActivityLaunchSideEffects(yellowBrickRoad, ozActivity, null); final ResourceTypeDefinition resourceType = mock(ResourceTypeDefinition.class); when(resourceType.accept(path)).thenReturn(false); final Collection<PathPlaceRequest> resolvedActivities = placeManager .getActivitiesForResourceType(resourceType); assertNotNull(resolvedActivities); assertEquals(0, resolvedActivities.size()); } @Test public void testGetActivitiesForResourceType_Matches() throws Exception { final ObservablePath path = mock(ObservablePath.class); final PathPlaceRequest yellowBrickRoad = new FakePathPlaceRequest(path); final WorkbenchScreenActivity ozActivity = mock(WorkbenchScreenActivity.class); when(activityManager.getActivities(yellowBrickRoad)).thenReturn(singleton((Activity) ozActivity)); when(ozActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); placeManager.goTo(yellowBrickRoad); verifyActivityLaunchSideEffects(yellowBrickRoad, ozActivity, null); final ResourceTypeDefinition resourceType = mock(ResourceTypeDefinition.class); when(resourceType.accept(path)).thenReturn(true); final Collection<PathPlaceRequest> resolvedActivities = placeManager .getActivitiesForResourceType(resourceType); assertNotNull(resolvedActivities); assertEquals(1, resolvedActivities.size()); try { resolvedActivities.clear(); fail("PlaceManager.getActivitiesForResourceType() should return an unmodifiable collection."); } catch (UnsupportedOperationException uoe) { //This is correct. The result should be an unmodifiable collection } } @Test public void testCloseAllPlacesOrNothingSucceeds() throws Exception { PlaceRequest emeraldCityPlace = new DefaultPlaceRequest("emerald_city"); WorkbenchScreenActivity emeraldCityActivity = createWorkbenchScreenActivity(emeraldCityPlace); placeManager.goTo(emeraldCityPlace); when(kansasActivity.onMayClose()).thenReturn(true); when(kansasActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); placeManager.closeAllPlacesOrNothing(); verifyPlaceClosed(kansas, kansasActivity); verifyPlaceClosed(emeraldCityPlace, emeraldCityActivity); } @Test public void testCloseAllPlacesOrNothingFails() throws Exception { PlaceRequest emeraldCityPlace = new DefaultPlaceRequest("emerald_city"); WorkbenchScreenActivity emeraldCityActivity = createWorkbenchScreenActivity(emeraldCityPlace); doReturn(false).when(emeraldCityActivity).onMayClose(); placeManager.goTo(emeraldCityPlace); when(kansasActivity.onMayClose()).thenReturn(true); when(kansasActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); placeManager.closeAllPlacesOrNothing(); verifyPlaceNotClosed(kansas, kansasActivity); verifyPlaceNotClosed(emeraldCityPlace, emeraldCityActivity); } private WorkbenchScreenActivity createWorkbenchScreenActivity(final PlaceRequest emeraldCityPlace) { WorkbenchScreenActivity emeraldCityActivity = mock(WorkbenchScreenActivity.class); when(emeraldCityActivity.onMayClose()).thenReturn(true); when(emeraldCityActivity.preferredWidth()).thenReturn(555); when(emeraldCityActivity.preferredHeight()).thenReturn(-1); when(emeraldCityActivity.isType(ActivityResourceType.SCREEN.name())).thenReturn(true); when(activityManager.getActivities(emeraldCityPlace)) .thenReturn(singleton((Activity) emeraldCityActivity)); return emeraldCityActivity; } private void verifyPlaceClosed(final PlaceRequest place, final WorkbenchScreenActivity screenActivity) { verify(workbenchPartBeforeCloseEvent).fire(refEq(new BeforeClosePlaceEvent(place, true, true))); verify(workbenchPartCloseEvent).fire(refEq(new ClosePlaceEvent(place))); verify(screenActivity).onMayClose(); verify(screenActivity).onClose(); verify(screenActivity, never()).onShutdown(); verify(activityManager).destroyActivity(screenActivity); verify(panelManager).removePartForPlace(place); assertEquals(PlaceStatus.CLOSE, placeManager.getStatus(place)); assertNull(placeManager.getActivity(place)); assertFalse(placeManager.getActivePlaceRequests().contains(place)); } private void verifyPlaceNotClosed(final PlaceRequest place, final WorkbenchScreenActivity screenActivity) { verify(workbenchPartBeforeCloseEvent, never()).fire(refEq(new BeforeClosePlaceEvent(place, true, true))); verify(workbenchPartCloseEvent, never()).fire(refEq(new ClosePlaceEvent(place))); verify(screenActivity, never()).onClose(); verify(screenActivity, never()).onShutdown(); verify(activityManager, never()).destroyActivity(screenActivity); verify(panelManager, never()).removePartForPlace(place); assertEquals(PlaceStatus.OPEN, placeManager.getStatus(place)); assertNotNull(placeManager.getActivity(place)); assertTrue(placeManager.getActivePlaceRequests().contains(place)); } /** * Verifies that all the expected side effects of a screen or editor activity launch have happened. * @param placeRequest The place request that was passed to some variant of PlaceManager.goTo(). * @param activity <b>A Mockito mock<b> of the activity that was resolved for <tt>placeRequest</tt>. */ private void verifyActivityLaunchSideEffects(PlaceRequest placeRequest, WorkbenchActivity activity, PanelDefinition expectedPanel) { // as of UberFire 0.4. this event only happens if the place is already visible. // it might be be better if the event was fired unconditionally. needs investigation. verify(selectWorkbenchPartEvent, never()).fire(any(SelectPlaceEvent.class)); // we know the activity was created (or we wouldn't be here), but should verify that only happened one time verify(activityManager, times(1)).getActivities(placeRequest); // contract between PlaceManager and PanelManager Integer preferredWidth = activity.preferredWidth(); Integer preferredHeight = activity.preferredHeight(); Integer expectedPartWidth; Integer expectedPartHeight; if (expectedPanel == null) { PanelDefinition rootPanel = panelManager.getRoot(); verify(panelManager).addWorkbenchPanel(rootPanel, null, preferredHeight, preferredWidth, null, null); expectedPartWidth = null; expectedPartHeight = null; } else { expectedPartWidth = expectedPanel.getWidth(); expectedPartHeight = expectedPanel.getHeight(); } verify(panelManager).addWorkbenchPart(eq(placeRequest), eq(new PartDefinitionImpl(placeRequest)), expectedPanel == null ? any(PanelDefinition.class) : eq( expectedPanel), isNull(Menus.class), any(UIPart.class), isNull(String.class), eq(expectedPartWidth), eq(expectedPartHeight)); // contract between PlaceManager and PlaceHistoryHandler verify(placeHistoryHandler).onPlaceChange(placeRequest); // state changes in PlaceManager itself (contract between PlaceManager and everyone) assertTrue("Actual place requests: " + placeManager.getActivePlaceRequests(), placeManager.getActivePlaceRequests().contains(placeRequest)); assertSame(activity, placeManager.getActivity(placeRequest)); assertEquals(PlaceStatus.OPEN, placeManager.getStatus(placeRequest)); // contract between PlaceManager and Activity verify(activity, never()).onStartup(any(PlaceRequest.class)); // this is ActivityManager's job verify(activity, times(1)).onOpen(); } // TODO test going to an unresolvable/unknown place // TODO test going to a place with a specific target panel (part of the PerspectiveManager/PlaceManager contract) // TODO test closing all panels when there are a variety of different types of panels open // TODO compare/contrast closeAllPlaces with closeAllCurrentPanels (former is public API; latter is called before launching a new perspective) /** * Verifies that the "place change" side effects have not happened, and that the given activity is still current. * @param expectedCurrentPlace The place request that placeManager should still consider "current." * @param activity <b>A Mockito mock<b> of the activity tied to <tt>expectedCurrentPlace</tt>. */ private void verifyNoActivityLaunchSideEffects(PlaceRequest expectedCurrentPlace, WorkbenchScreenActivity activity) { // contract between PlaceManager and PanelManager verify(panelManager, never()).addWorkbenchPanel(eq(panelManager.getRoot()), any(Position.class), any(Integer.class), any(Integer.class), any(Integer.class), any(Integer.class)); verify(panelManager, never()).addWorkbenchPanel(eq(panelManager.getRoot()), any(PanelDefinition.class), any(Position.class)); // contract between PlaceManager and PlaceHistoryHandler verify(placeHistoryHandler, never()).onPlaceChange(any(PlaceRequest.class)); // state changes in PlaceManager itself (contract between PlaceManager and everyone) assertTrue( "Actual place requests: " + placeManager.getActivePlaceRequests(), placeManager.getActivePlaceRequests().contains(expectedCurrentPlace)); assertSame(activity, placeManager.getActivity(expectedCurrentPlace)); assertEquals(PlaceStatus.OPEN, placeManager.getStatus(expectedCurrentPlace)); // contract between PlaceManager and Activity verify(activity, never()).onStartup(any(PlaceRequest.class)); verify(activity, never()).onOpen(); } class FakePathPlaceRequest extends PathPlaceRequest { final ObservablePath path; FakePathPlaceRequest(ObservablePath path) { this.path = path; } @Override public ObservablePath getPath() { return path; } @Override public int hashCode() { return 42; } } }