/* * 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.mvp; import java.util.Arrays; import java.util.List; import javax.enterprise.event.Event; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; 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.client.workbench.PanelManager; import org.uberfire.client.workbench.WorkbenchServicesProxy; import org.uberfire.client.workbench.events.PerspectiveChange; import org.uberfire.client.workbench.panels.impl.MultiListWorkbenchPanelPresenter; import org.uberfire.client.workbench.panels.impl.SimpleWorkbenchPanelPresenter; import org.uberfire.mvp.Command; import org.uberfire.mvp.ParameterizedCommand; import org.uberfire.mvp.PlaceRequest; import org.uberfire.mvp.impl.DefaultPlaceRequest; import org.uberfire.workbench.model.CompassPosition; 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 static org.junit.Assert.*; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.refEq; import static org.mockito.Mockito.*; @RunWith(MockitoJUnitRunner.class) public class PerspectiveManagerTest { @Mock PlaceManager placeManager; @Mock PanelManager panelManager; @Mock ActivityManager activityManager; @Mock WorkbenchServicesProxy wbServices; @Mock Event<PerspectiveChange> perspectiveChangeEvent; @Mock ActivityBeansCache activityBeansCache; @InjectMocks PerspectiveManagerImpl perspectiveManager; // useful mocks provided by setup method private PerspectiveDefinition ozDefinition; private PerspectiveActivity oz; private PlaceRequest pr; private ParameterizedCommand<PerspectiveDefinition> doWhenFinished; private ParameterizedCommand<PerspectiveDefinition> doAfterFetch; private Command doWhenFinishedSave; private PerspectiveManagerImpl.FetchPerspectiveCommand fetchCommand; private List<PartDefinitionImpl> partDefinitionsRoot; private List<PartDefinitionImpl> partDefinitionRootChild1; private List<PartDefinitionImpl> partDefinitionRootChild2; private List<PartDefinitionImpl> partDefinitionRootChild2Child; @SuppressWarnings("unchecked") @Before public void setup() { ozDefinition = new PerspectiveDefinitionImpl(MultiListWorkbenchPanelPresenter.class.getName()); oz = mock(PerspectiveActivity.class); pr = mock(PlaceRequest.class); when(oz.getDefaultPerspectiveLayout()).thenReturn(ozDefinition); when(oz.getIdentifier()).thenReturn("oz_perspective"); when(oz.isTransient()).thenReturn(true); doWhenFinished = mock(ParameterizedCommand.class); doAfterFetch = spy(new ParameterizedCommand<PerspectiveDefinition>() { @Override public void execute(final PerspectiveDefinition parameter) { } }); doWhenFinishedSave = mock(Command.class); fetchCommand = spy(perspectiveManager.new FetchPerspectiveCommand(oz, doAfterFetch)); // simulate "finished saving" callback on wbServices.save() doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { Command callback = (Command) invocation.getArguments()[2]; callback.execute(); return null; } }).when(wbServices).save(any(String.class), any(PerspectiveDefinition.class), any(Command.class)); // simulate "no saved state found" result on wbServices.loadPerspective() doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { ParameterizedCommand<?> callback = (ParameterizedCommand<?>) invocation.getArguments()[1]; callback.execute(null); return null; } }).when(wbServices).loadPerspective(anyString(), any(ParameterizedCommand.class)); // XXX should look at why PanelManager needs to return an alternative panel sometimes. // would be better if addWorkbenchPanel returned void. when(panelManager.addWorkbenchPanel(any(PanelDefinition.class), any(PanelDefinition.class), any(Position.class))).thenAnswer(new Answer<PanelDefinition>() { @Override public PanelDefinition answer(InvocationOnMock invocation) { return (PanelDefinition) invocation.getArguments()[1]; } }); } @Test public void shouldReportNullPerspectiveInitially() throws Exception { assertNull(perspectiveManager.getCurrentPerspective()); } @Test public void shouldReportNewPerspectiveAsCurrentAfterSwitching() throws Exception { perspectiveManager.switchToPerspective(pr, oz, doWhenFinished); assertSame(oz, perspectiveManager.getCurrentPerspective()); } @Test public void shouldSaveNonTransientPerspectives() throws Exception { PerspectiveDefinition kansasDefinition = new PerspectiveDefinitionImpl(MultiListWorkbenchPanelPresenter.class.getName()); PerspectiveActivity kansas = mock(PerspectiveActivity.class); when(kansas.getDefaultPerspectiveLayout()).thenReturn(kansasDefinition); when(kansas.getIdentifier()).thenReturn("kansas_perspective"); when(kansas.isTransient()).thenReturn(false); perspectiveManager.switchToPerspective(pr, kansas, doWhenFinished); perspectiveManager.savePerspectiveState(doWhenFinishedSave); verify(wbServices).save(eq("kansas_perspective"), eq(kansasDefinition), eq(doWhenFinishedSave)); } @Test public void shouldNotSaveTransientPerspectives() throws Exception { PerspectiveDefinition kansasDefinition = new PerspectiveDefinitionImpl(MultiListWorkbenchPanelPresenter.class.getName()); PerspectiveActivity kansas = mock(PerspectiveActivity.class); when(kansas.getDefaultPerspectiveLayout()).thenReturn(kansasDefinition); when(kansas.getIdentifier()).thenReturn("kansas_perspective"); when(kansas.isTransient()).thenReturn(true); perspectiveManager.switchToPerspective(pr, kansas, doWhenFinished); perspectiveManager.savePerspectiveState(doWhenFinishedSave); verify(wbServices, never()).save(any(String.class), eq(kansasDefinition), any(Command.class)); } @SuppressWarnings("unchecked") @Test public void shouldLoadNewNonTransientPerspectiveState() throws Exception { when(oz.isTransient()).thenReturn(false); perspectiveManager.switchToPerspective(pr, oz, doWhenFinished); verify(wbServices).loadPerspective(eq("oz_perspective"), any(ParameterizedCommand.class)); } @SuppressWarnings("unchecked") @Test public void shouldNotLoadNewTransientPerspectiveState() throws Exception { when(oz.isTransient()).thenReturn(true); perspectiveManager.switchToPerspective(pr, oz, doWhenFinished); verify(wbServices, never()).loadPerspective(eq("oz_perspective"), any(ParameterizedCommand.class)); } @Test public void shouldExecuteCallbackWhenDoneLaunchingPerspective() throws Exception { perspectiveManager.switchToPerspective(pr, oz, doWhenFinished); verify(doWhenFinished).execute(ozDefinition); } @Test public void shouldFireEventWhenLaunchingNewPerspective() throws Exception { perspectiveManager.switchToPerspective(pr, oz, doWhenFinished); verify(perspectiveChangeEvent).fire(refEq(new PerspectiveChange(pr, ozDefinition, null, "oz_perspective"))); } @Test public void shouldAddAllPanelsToPanelManager() throws Exception { PanelDefinition westPanel = new PanelDefinitionImpl(MultiListWorkbenchPanelPresenter.class.getName()); PanelDefinition eastPanel = new PanelDefinitionImpl(MultiListWorkbenchPanelPresenter.class.getName()); PanelDefinition northPanel = new PanelDefinitionImpl(MultiListWorkbenchPanelPresenter.class.getName()); PanelDefinition southPanel = new PanelDefinitionImpl(MultiListWorkbenchPanelPresenter.class.getName()); PanelDefinition southWestPanel = new PanelDefinitionImpl(MultiListWorkbenchPanelPresenter.class.getName()); ozDefinition.getRoot().appendChild(CompassPosition.WEST, westPanel); ozDefinition.getRoot().appendChild(CompassPosition.EAST, eastPanel); ozDefinition.getRoot().appendChild(CompassPosition.NORTH, northPanel); ozDefinition.getRoot().appendChild(CompassPosition.SOUTH, southPanel); southPanel.appendChild(CompassPosition.WEST, southWestPanel); // we assume this will be set correctly (verified elsewhere) when(panelManager.getRoot()).thenReturn(ozDefinition.getRoot()); perspectiveManager.switchToPerspective(pr, oz, doWhenFinished); verify(panelManager).addWorkbenchPanel(ozDefinition.getRoot(), westPanel, CompassPosition.WEST); verify(panelManager).addWorkbenchPanel(ozDefinition.getRoot(), eastPanel, CompassPosition.EAST); verify(panelManager).addWorkbenchPanel(ozDefinition.getRoot(), northPanel, CompassPosition.NORTH); verify(panelManager).addWorkbenchPanel(ozDefinition.getRoot(), southPanel, CompassPosition.SOUTH); verify(panelManager).addWorkbenchPanel(southPanel, southWestPanel, CompassPosition.WEST); } @Test public void shouldDestroyAllOldPanelsWhenSwitchingRoot() throws Exception { PerspectiveDefinition fooPerspectiveDef = new PerspectiveDefinitionImpl(MultiListWorkbenchPanelPresenter.class.getName()); PanelDefinition rootPanel = fooPerspectiveDef.getRoot(); PanelDefinition fooPanel = new PanelDefinitionImpl(SimpleWorkbenchPanelPresenter.class.getName()); PanelDefinition fooChildPanel = new PanelDefinitionImpl(SimpleWorkbenchPanelPresenter.class.getName()); PanelDefinition barPanel = new PanelDefinitionImpl(SimpleWorkbenchPanelPresenter.class.getName()); PanelDefinition bazPanel = new PanelDefinitionImpl(SimpleWorkbenchPanelPresenter.class.getName()); rootPanel.appendChild(fooPanel); rootPanel.appendChild(barPanel); rootPanel.appendChild(bazPanel); fooPanel.appendChild(fooChildPanel); PerspectiveActivity fooPerspective = mock(PerspectiveActivity.class); when(fooPerspective.getDefaultPerspectiveLayout()).thenReturn(fooPerspectiveDef); when(fooPerspective.isTransient()).thenReturn(true); perspectiveManager.switchToPerspective(pr, fooPerspective, doWhenFinished); perspectiveManager.switchToPerspective(pr, oz, doWhenFinished); verify(panelManager).removeWorkbenchPanel(fooPanel); verify(panelManager).removeWorkbenchPanel(fooChildPanel); verify(panelManager).removeWorkbenchPanel(barPanel); verify(panelManager).removeWorkbenchPanel(bazPanel); verify(panelManager, never()).removeWorkbenchPanel(rootPanel); } @Test public void fetchPerspectiveCommandForAnInvalidDefinitionShouldLoadedPerspectiveDefinitionTest() throws Exception { when(oz.isTransient()).thenReturn(false); when(fetchCommand.isAValidDefinition(any())).thenReturn(false); fetchCommand.execute(); assertEquals(oz, perspectiveManager.getCurrentPerspective()); verify(doAfterFetch).execute(eq(ozDefinition)); } @Test public void fetchPerspectivesForTransientPerspectivesShouldAlwaysLoadDefaultLayoutTest() throws Exception { when(fetchCommand.isAValidDefinition(any())).thenReturn(true); fetchCommand.execute(); assertEquals(oz, perspectiveManager.getCurrentPerspective()); verify(doAfterFetch).execute(eq(ozDefinition)); } @Test public void isAValidPerspectiveDefinitionTest() throws Exception { createPartDefinitions(); when(activityBeansCache.hasActivity(any())).thenReturn(true); assertTrue(fetchCommand.isAValidDefinition(createPerspectiveDefinition())); verify(activityBeansCache, times(getTotalOfPartDefinitions())).hasActivity(any()); } @Test public void isAnInvalidPerspectiveDefinitionTest() throws Exception { when(activityBeansCache.hasActivity(any())).thenReturn(true); assertFalse(fetchCommand.isAValidDefinition(null)); } @Test public void isAnInvalidPerspectiveDefinition2Test() throws Exception { createPartDefinitions(); when(activityBeansCache.hasActivity(any())).thenReturn(true); when(activityBeansCache.hasActivity("part3-rootChild2")).thenReturn(false); assertFalse(fetchCommand.isAValidDefinition(createPerspectiveDefinition())); } private PerspectiveDefinition createPerspectiveDefinition() { PerspectiveDefinitionImpl perspectiveDefinition = new PerspectiveDefinitionImpl(); PanelDefinition root = perspectiveDefinition.getRoot(); partDefinitionsRoot.forEach(p -> root.addPart(p)); PanelDefinitionImpl rootChild1 = new PanelDefinitionImpl("org.uberfire.client.workbench.panels.impl.MultiTabWorkbenchPanelPresenter"); partDefinitionRootChild1.forEach(p -> rootChild1.addPart(p)); PanelDefinitionImpl rootChild2 = new PanelDefinitionImpl("org.uberfire.client.workbench.panels.impl.MultiTabWorkbenchPanelPresenter"); partDefinitionRootChild2.forEach(p -> rootChild2.addPart(p)); PanelDefinitionImpl rootChild2Child = new PanelDefinitionImpl("org.uberfire.client.workbench.panels.impl.MultiTabWorkbenchPanelPresenter"); partDefinitionRootChild2Child.forEach(p -> rootChild2Child.addPart(p)); root.insertChild(mock(Position.class), rootChild1); rootChild2.insertChild(mock(Position.class), rootChild2Child); root.insertChild(mock(Position.class), rootChild2); return perspectiveDefinition; } private void createPartDefinitions() { partDefinitionsRoot = Arrays.asList(new PartDefinitionImpl(new DefaultPlaceRequest("part1")), new PartDefinitionImpl(new DefaultPlaceRequest("part2"))); partDefinitionRootChild1 = Arrays.asList(new PartDefinitionImpl(new DefaultPlaceRequest("part1-rootChild1")), new PartDefinitionImpl(new DefaultPlaceRequest("part2-rootChild1")), new PartDefinitionImpl(new DefaultPlaceRequest("part3-rootChild1"))); partDefinitionRootChild2 = Arrays.asList(new PartDefinitionImpl(new DefaultPlaceRequest("part1-rootChild2")), new PartDefinitionImpl(new DefaultPlaceRequest("part2-rootChild2")), new PartDefinitionImpl(new DefaultPlaceRequest("part3-rootChild2"))); partDefinitionRootChild2Child = Arrays.asList(new PartDefinitionImpl(new DefaultPlaceRequest("part1-rootChild2Child")), new PartDefinitionImpl(new DefaultPlaceRequest("part2-rootChild2Child")), new PartDefinitionImpl(new DefaultPlaceRequest("part3-rootChild2Child")), new PartDefinitionImpl(new DefaultPlaceRequest("part4-rootChild2Child"))); } private int getTotalOfPartDefinitions() { int total = partDefinitionsRoot.size() + partDefinitionRootChild1.size() + partDefinitionRootChild2.size() + partDefinitionRootChild2Child.size(); return total; } }