/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.ide.part.editor;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwtmockito.GwtMockitoTestRunner;
import com.google.inject.Provider;
import com.google.web.bindery.event.shared.Event;
import com.google.web.bindery.event.shared.EventBus;
import com.google.web.bindery.event.shared.HandlerRegistration;
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
import org.eclipse.che.ide.actions.EditorActions;
import org.eclipse.che.ide.api.action.Action;
import org.eclipse.che.ide.api.action.ActionManager;
import org.eclipse.che.ide.api.action.Presentation;
import org.eclipse.che.ide.api.editor.AbstractEditorPresenter;
import org.eclipse.che.ide.api.editor.EditorAgent;
import org.eclipse.che.ide.api.editor.EditorInput;
import org.eclipse.che.ide.api.editor.EditorPartPresenter;
import org.eclipse.che.ide.api.editor.EditorWithErrors;
import org.eclipse.che.ide.api.parts.EditorTab;
import org.eclipse.che.ide.api.parts.PartPresenter;
import org.eclipse.che.ide.api.parts.PartStackView.TabItem;
import org.eclipse.che.ide.api.parts.PropertyListener;
import org.eclipse.che.ide.api.resources.VirtualFile;
import org.eclipse.che.ide.menu.PartMenu;
import org.eclipse.che.ide.part.PartStackPresenter.PartStackEventHandler;
import org.eclipse.che.ide.part.PartsComparator;
import org.eclipse.che.ide.part.editor.actions.CloseAllTabsPaneAction;
import org.eclipse.che.ide.part.editor.actions.ClosePaneAction;
import org.eclipse.che.ide.part.editor.actions.SplitHorizontallyAction;
import org.eclipse.che.ide.part.editor.actions.SplitVerticallyAction;
import org.eclipse.che.ide.part.widgets.TabItemFactory;
import org.eclipse.che.ide.part.widgets.panemenu.EditorPaneMenu;
import org.eclipse.che.ide.part.widgets.panemenu.EditorPaneMenuItem;
import org.eclipse.che.ide.part.widgets.panemenu.EditorPaneMenuItemFactory;
import org.eclipse.che.ide.part.widgets.panemenu.PaneMenuActionItemWidget;
import org.eclipse.che.ide.resource.Path;
import org.eclipse.che.ide.ui.toolbar.PresentationFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.vectomatic.dom.svg.ui.SVGResource;
import static org.eclipse.che.ide.part.editor.actions.EditorAbstractAction.CURRENT_FILE_PROP;
import static org.eclipse.che.ide.part.editor.actions.EditorAbstractAction.CURRENT_PANE_PROP;
import static org.eclipse.che.ide.part.editor.actions.EditorAbstractAction.CURRENT_TAB_PROP;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* @author Dmitry Shnurenko
*/
@RunWith(GwtMockitoTestRunner.class)
public class EditorPartStackPresenterTest {
private static final String SOME_TEXT = "someText";
//constructor mocks
@Mock
private EditorPartStackView view;
@Mock
private PartMenu partMenu;
@Mock
private PartsComparator partsComparator;
@Mock
private EventBus eventBus;
@Mock
private TabItemFactory tabItemFactory;
@Mock
private PartStackEventHandler partStackEventHandler;
@Mock
private EditorPaneMenu editorPaneMenu;
@Mock
private Provider<EditorAgent> editorAgentProvider;
@Mock
private PresentationFactory presentationFactory;
@Mock
private ActionManager actionManager;
@Mock
private ClosePaneAction closePaneAction;
@Mock
private CloseAllTabsPaneAction closeAllTabsPaneAction;
@Mock
private EditorPaneMenuItemFactory editorPaneMenuItemFactory;
@Mock
private EditorAgent editorAgent;
//additional mocks
@Mock
private SplitHorizontallyAction splitHorizontallyAction;
@Mock
private SplitVerticallyAction splitVerticallyAction;
@Mock
private Presentation presentation;
@Mock
private EditorTab editorTab1;
@Mock
private EditorTab editorTab2;
@Mock
private EditorTab editorTab3;
@Mock
private EditorWithErrors withErrorsPart;
@Mock
private AbstractEditorPresenter partPresenter1;
@Mock
private AbstractEditorPresenter partPresenter2;
@Mock
private AbstractEditorPresenter partPresenter3;
@Mock
private EditorPaneMenuItem<Action> editorPaneActionMenuItem;
@Mock
private EditorPaneMenuItem<TabItem> editorPaneTabMenuItem;
@Mock
private SVGResource resource1;
@Mock
private SVGResource resource2;
@Mock
private ProjectConfigDto descriptor;
@Mock
private EditorPartPresenter editorPartPresenter;
@Mock
private EditorInput editorInput1;
@Mock
private EditorInput editorInput2;
@Mock
private EditorInput editorInput3;
@Mock
private VirtualFile file1;
@Mock
private VirtualFile file2;
@Mock
private VirtualFile file3;
@Mock
private HandlerRegistration handlerRegistration;
@Captor
private ArgumentCaptor<EditorPaneMenuItem> itemCaptor;
@Captor
private ArgumentCaptor<AsyncCallback<Void>> argumentCaptor;
private EditorPartStackPresenter presenter;
@Before
public void setUp() {
when(partPresenter1.getTitle()).thenReturn(SOME_TEXT);
when(partPresenter1.getTitleImage()).thenReturn(resource1);
when(partPresenter2.getTitle()).thenReturn(SOME_TEXT);
when(partPresenter2.getTitleImage()).thenReturn(resource2);
when(partPresenter1.getEditorInput()).thenReturn(editorInput1);
when(editorInput1.getFile()).thenReturn(file1);
when(partPresenter2.getEditorInput()).thenReturn(editorInput2);
when(editorInput2.getFile()).thenReturn(file2);
when(partPresenter3.getEditorInput()).thenReturn(editorInput3);
when(editorInput3.getFile()).thenReturn(file3);
when(presentationFactory.getPresentation((Action)anyObject())).thenReturn(presentation);
when(eventBus.addHandler((Event.Type<Object>)anyObject(), anyObject())).thenReturn(handlerRegistration);
when(actionManager.getAction(EditorActions.SPLIT_HORIZONTALLY)).thenReturn(splitHorizontallyAction);
when(actionManager.getAction(EditorActions.SPLIT_VERTICALLY)).thenReturn(splitVerticallyAction);
when(closePaneAction.getTemplatePresentation()).thenReturn(presentation);
when(closeAllTabsPaneAction.getTemplatePresentation()).thenReturn(presentation);
when(splitHorizontallyAction.getTemplatePresentation()).thenReturn(presentation);
when(splitVerticallyAction.getTemplatePresentation()).thenReturn(presentation);
when(editorPaneMenuItemFactory.createMenuItem((Action)anyObject())).thenReturn(editorPaneActionMenuItem);
when(editorPaneMenuItemFactory.createMenuItem((TabItem)anyObject())).thenReturn(editorPaneTabMenuItem);
presenter = new EditorPartStackPresenter(view,
partMenu,
partsComparator,
editorPaneMenuItemFactory,
presentationFactory,
eventBus,
tabItemFactory,
partStackEventHandler,
editorPaneMenu,
actionManager,
closePaneAction,
closeAllTabsPaneAction,
editorAgent);
when(tabItemFactory.createEditorPartButton(partPresenter1, presenter)).thenReturn(editorTab1);
when(tabItemFactory.createEditorPartButton(partPresenter2, presenter)).thenReturn(editorTab2);
when(tabItemFactory.createEditorPartButton(partPresenter3, presenter)).thenReturn(editorTab3);
when(editorTab1.getFile()).thenReturn(file1);
}
@Test
public void constructorShouldBeVerified() {
verify(view, times(2)).setDelegate(presenter);
verify(view).addPaneMenuButton(editorPaneMenu);
verify(editorPaneMenuItemFactory, times(4)).createMenuItem(Matchers.<Action>anyObject());
verify(editorPaneMenu).addItem(Matchers.<PaneMenuActionItemWidget>anyObject(), eq(true));
verify(editorPaneMenu, times(3)).addItem(Matchers.<PaneMenuActionItemWidget>anyObject());
}
@Test
public void focusShouldBeSet() {
presenter.setFocus(true);
verify(view).setFocus(true);
}
@Test
public void partShouldBeAdded() {
presenter.addPart(partPresenter1);
verify(partPresenter1, times(2)).addPropertyListener(Matchers.<PropertyListener>anyObject());
verify(tabItemFactory).createEditorPartButton(partPresenter1, presenter);
verify(editorTab1).setDelegate(presenter);
verify(view).addTab(editorTab1, partPresenter1);
verify(view).selectTab(partPresenter1);
}
@Test
public void partShouldNotBeAddedWhenItExist() {
presenter.addPart(partPresenter1);
reset(view);
presenter.addPart(partPresenter1);
verify(view, never()).addTab(editorTab1, partPresenter1);
verify(view).selectTab(partPresenter1);
}
@Test
public void activePartShouldBeReturned() {
presenter.setActivePart(partPresenter1);
assertEquals(presenter.getActivePart(), partPresenter1);
}
@Test
public void onTabShouldBeClicked() {
presenter.addPart(partPresenter1);
reset(view);
presenter.onTabClicked(editorTab1);
verify(view).selectTab(partPresenter1);
}
@Test
public void tabShouldBeClosed() {
presenter.addPart(partPresenter1);
presenter.removePart(partPresenter1);
presenter.onTabClose(editorTab1);
verify(view).removeTab(partPresenter1);
}
@Test
public void activePartShouldBeChangedWhenWeClickOnTab() {
presenter.addPart(partPresenter1);
presenter.addPart(partPresenter2);
presenter.onTabClicked(editorTab1);
assertEquals(presenter.getActivePart(), partPresenter1);
presenter.onTabClicked(editorTab2);
assertEquals(presenter.getActivePart(), partPresenter2);
}
@Test
public void previousTabSelectedWhenWeRemovePart() {
presenter.addPart(partPresenter1);
presenter.addPart(partPresenter2);
presenter.onTabClicked(editorTab2);
presenter.removePart(partPresenter2);
presenter.onTabClose(editorTab2);
assertEquals(presenter.getActivePart(), partPresenter1);
}
@Test
public void activePartShouldBeNullWhenWeCloseAllParts() {
presenter.addPart(partPresenter1);
presenter.onTabClose(editorTab1);
assertThat(presenter.getActivePart(), is(nullValue()));
}
@Test
public void shouldReturnNextPart() {
presenter.addPart(partPresenter1);
presenter.addPart(partPresenter2);
presenter.addPart(partPresenter3);
EditorPartPresenter result = presenter.getNextFor(partPresenter2);
assertNotNull(result);
assertEquals(partPresenter3, result);
}
@Test
public void shouldReturnFirstPart() {
presenter.addPart(partPresenter1);
presenter.addPart(partPresenter2);
presenter.addPart(partPresenter3);
EditorPartPresenter result = presenter.getNextFor(partPresenter3);
assertNotNull(result);
assertEquals(partPresenter1, result);
}
@Test
public void shouldReturnPreviousPart() {
presenter.addPart(partPresenter1);
presenter.addPart(partPresenter2);
presenter.addPart(partPresenter3);
EditorPartPresenter result = presenter.getPreviousFor(partPresenter2);
assertNotNull(result);
assertEquals(partPresenter1, result);
}
@Test
public void shouldReturnLastPart() {
presenter.addPart(partPresenter1);
presenter.addPart(partPresenter2);
presenter.addPart(partPresenter3);
EditorPartPresenter result = presenter.getPreviousFor(partPresenter1);
assertNotNull(result);
assertEquals(partPresenter3, result);
}
@Test
public void tabShouldBeReturnedByPath() throws Exception {
Path path = new Path(SOME_TEXT);
when(editorTab1.getFile()).thenReturn(file1);
when(file1.getLocation()).thenReturn(path);
presenter.addPart(partPresenter1);
assertEquals(editorTab1, presenter.getTabByPath(path));
}
@Test
public void shouldAddHandlers() throws Exception {
presenter.addPart(partPresenter1);
verify(eventBus, times(2)).addHandler((Event.Type<EditorPartStackPresenter>)anyObject(), eq(presenter));
}
@Test
public void shouldNotAddHandlersWhenHandlersAlreadyExist() throws Exception {
presenter.addPart(partPresenter1);
reset(eventBus);
presenter.addPart(partPresenter2);
verify(eventBus, never()).addHandler((Event.Type<EditorPartStackPresenter>)anyObject(), eq(presenter));
}
@Test
public void shouldRemoveHandlersWhenPartsIsAbsent() throws Exception {
presenter.addPart(partPresenter1);
reset(handlerRegistration);
presenter.removePart(partPresenter1);
verify(handlerRegistration, times(2)).removeHandler();
}
@Test
public void shouldAvoidNPEWhenHandlersAlreadyRemoved() throws Exception {
presenter.addPart(partPresenter1);
presenter.removePart(partPresenter1);
reset(handlerRegistration);
presenter.removePart(partPresenter2);
verify(handlerRegistration, never()).removeHandler();
}
@Test
public void openPreviousActivePartTest() {
presenter.addPart(partPresenter1);
presenter.openPreviousActivePart();
verify(view).selectTab(eq(partPresenter1));
}
@Test
public void onTabItemClickedTest() {
TabItem tabItem = mock(TabItem.class);
when(editorPaneTabMenuItem.getData()).thenReturn(tabItem);
presenter.paneMenuTabItemHandler.onItemClicked(editorPaneTabMenuItem);
verify(view).selectTab((PartPresenter)anyObject());
}
@Test
public void onActionClickedTest() {
Action action = mock(Action.class);
when(editorPaneActionMenuItem.getData()).thenReturn(action);
presenter.addPart(partPresenter1);
presenter.setActivePart(partPresenter1);
presenter.paneMenuActionItemHandler.onItemClicked(editorPaneActionMenuItem);
verify(presentation).putClientProperty(eq(CURRENT_PANE_PROP), eq(presenter));
verify(presentation).putClientProperty(eq(CURRENT_TAB_PROP), eq(editorTab1));
verify(presentation).putClientProperty(eq(CURRENT_FILE_PROP), eq(file1));
}
@Test
public void onItemCloseTest() {
when(editorPaneTabMenuItem.getData()).thenReturn(editorTab1);
presenter.paneMenuTabItemHandler.onCloseButtonClicked(editorPaneTabMenuItem);
verify(editorAgent).closeEditor(any(EditorPartPresenter.class));
}
}