/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 de.unioninvestment.eai.portal.portlet.crud; import com.liferay.portal.kernel.util.WebKeys; import com.liferay.portal.theme.ThemeDisplay; import com.vaadin.server.Page; import com.vaadin.server.VaadinService; import com.vaadin.server.VaadinSession; import com.vaadin.server.WebBrowser; import com.vaadin.ui.*; import de.unioninvestment.eai.portal.portlet.crud.config.PortletConfig; import de.unioninvestment.eai.portal.portlet.crud.config.resource.Config; import de.unioninvestment.eai.portal.portlet.crud.domain.events.ShowPopupEvent; import de.unioninvestment.eai.portal.portlet.crud.domain.model.ModelBuilder; import de.unioninvestment.eai.portal.portlet.crud.domain.model.ModelFactory; import de.unioninvestment.eai.portal.portlet.crud.domain.model.ModelPreferences; import de.unioninvestment.eai.portal.portlet.crud.domain.model.Portlet; import de.unioninvestment.eai.portal.portlet.crud.domain.validation.ModelValidator; import de.unioninvestment.eai.portal.portlet.crud.mvp.presenters.PortletPresenter; import de.unioninvestment.eai.portal.portlet.crud.mvp.presenters.PresenterFactory; import de.unioninvestment.eai.portal.portlet.crud.mvp.presenters.configuration.PortletConfigurationPresenter; import de.unioninvestment.eai.portal.portlet.crud.mvp.views.PortletView; import de.unioninvestment.eai.portal.portlet.crud.mvp.views.configuration.PortletConfigurationView; import de.unioninvestment.eai.portal.portlet.crud.mvp.views.ui.BusinessExceptionMessage; import de.unioninvestment.eai.portal.portlet.crud.scripting.model.ScriptModelBuilder; import de.unioninvestment.eai.portal.portlet.crud.scripting.model.ScriptModelFactory; import de.unioninvestment.eai.portal.portlet.crud.services.ConfigurationService; import de.unioninvestment.eai.portal.portlet.test.commons.SpringPortletContextTest; import de.unioninvestment.eai.portal.support.vaadin.CrudVaadinPortlet; import de.unioninvestment.eai.portal.support.vaadin.junit.LiferayContext; import de.unioninvestment.eai.portal.support.vaadin.mvp.EventBus; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.springframework.mock.web.portlet.MockPortalContext; import org.springframework.mock.web.portlet.MockPortletURL; import javax.portlet.*; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; import java.util.*; import java.util.concurrent.Future; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.isA; import static org.mockito.Mockito.*; public class CrudUITest extends SpringPortletContextTest { @InjectMocks private CrudUI ui = new CrudUI() { @Override public void accessSynchronously(Runnable runnable) throws com.vaadin.ui.UIDetachedException { runnable.run(); }; @Override public Future<Void> access(Runnable runnable) { runnable.run(); return null; }; protected org.springframework.context.ApplicationContext getSpringContext( com.vaadin.server.VaadinRequest request) { return null; }; public VaadinSession getSession() { return vaadinSession; }; public Page getPage() { return liferayContext.getPageMock(); }; }; @Mock private ConnectorTracker connectorTrackerMock; @Mock private UiHistory uiHistoryMock; @Mock private Settings settingsMock; @Mock private Portlet portletMock; @Mock private PortletPresenter portletPresenterMock; @Mock private PortletView portletViewMock; @Mock private ConfigurationService configurationServiceMock; @Mock private GuiBuilder guiBuilderMock; @Mock private EventBus eventBusMock; @Mock private ModelBuilder modelBuilderMock; @Mock private PresenterFactory presenterFactoryMock; @Mock private PortletConfigurationPresenter portletConfigurationPresenterMock; @Mock private PortletConfigurationView portletConfigurationViewMock; @Mock(name = "viewPage") private VerticalLayout viewPageMock; @Mock(name = "editPage") private ComponentContainer editPageMock; @Mock private transient ScriptModelFactory scriptModelFactoryMock; @Mock ScriptModelBuilder scriptModelBuilderMock; @Mock private ModelFactory modelFactoryMock; @Mock private Config configMock; @Mock private ThemeDisplay themeDisplayMock; @Mock private RenderRequest renderRequestMock; @Mock private RenderResponse renderResponseMock; @Mock private WebBrowser browserMock; @Rule public LiferayContext liferayContext = new LiferayContext("4711", 14008L); private VaadinSession vaadinSession; @Mock private VaadinService vaadinServiceMock; private PortletConfig portletConfig; @Before public void setUp() throws MalformedURLException { MockitoAnnotations.initMocks(this); when(settingsMock.getHelpUrl()).thenReturn("http://help.us"); when( ((ResourceResponse) liferayContext.getPortletResponseMock()) .createRenderURL()).thenReturn( new MockPortletURL(new MockPortalContext(), "myurl")); when( modelFactoryMock.getBuilder(isA(EventBus.class), isA(Config.class), isA(ModelPreferences.class))).thenReturn(modelBuilderMock); when(modelBuilderMock.build()).thenReturn(portletMock); when(presenterFactoryMock.portletConfigurationPresenter()).thenReturn( portletConfigurationPresenterMock); when(portletConfigurationPresenterMock.getView()).thenReturn( portletConfigurationViewMock); when(portletPresenterMock.getView()).thenReturn(portletViewMock); when(configurationServiceMock.getPortletConfig("4711", 14008)) .thenReturn(configMock); when(liferayContext.getPageMock().getLocation()).thenReturn( URI.create("http://localhost")); when( liferayContext.getPortletRequestMock().getAttribute( WebKeys.PORTLET_ID)).thenReturn("4711"); when( liferayContext.getPortletRequestMock().getAttribute( WebKeys.THEME_DISPLAY)).thenReturn(themeDisplayMock); when(themeDisplayMock.getScopeGroupId()).thenReturn(14008L); when(Page.getCurrent().getWebBrowser()).thenReturn(browserMock); when(browserMock.getLocale()).thenReturn(Locale.GERMANY); } /** * Bereitet die UserPrincipals und das Userrepository für die Tests vor, * sodass ein NamedUser mit den übergebenen Rollen ausgestattet ist. * * @param roles */ private void provideUserWithRoles(String... roles) { when(liferayContext.getVaadinPortletRequestMock().getRemoteUser()) .thenReturn("carsten"); final Set<String> roleSet = roles == null ? null : new HashSet<String>( Arrays.asList(roles)); when( liferayContext.getVaadinPortletRequestMock().isUserInRole( isA(String.class))).thenAnswer(new Answer<Boolean>() { @Override public Boolean answer(InvocationOnMock invocation) throws Throwable { return roleSet != null && roleSet.contains(invocation.getArguments()[0]); } }); } @Test public void shouldApplyPreferredBrowserLocale() { ui.init(liferayContext.getVaadinPortletRequestMock()); assertThat(ui.getLocale(), is(Locale.GERMANY)); } @Test public void shouldAddItselfToUiHistory() { ui.init(liferayContext.getVaadinPortletRequestMock()); verify(uiHistoryMock).add(ui); } @Test public void shouldReturnDefaultHistoryLimitFromSettings() { initializeUI(); ui.portletConfig = null; when(settingsMock.getUiHistoryLimit()).thenReturn(3); assertThat(ui.getHistoryLimit(), is(3)); } @Test public void shouldReturnSpecificHistoryLimitIfSet() { initializeUI(); stubPortletInitialization(); when(settingsMock.getUiHistoryLimit()).thenReturn(3); portletConfig.setHistoryLimit(4); assertThat(ui.getHistoryLimit(), is(4)); } @Test public void shouldRegisterFallbackErrorHandler() { provideUserWithRoles(); initializeUI(); verify(liferayContext.getVaadinSessionMock()).setErrorHandler( isA(CrudErrorHandler.class)); } private void initializeUI() { ui.init(liferayContext.getVaadinPortletRequestMock()); } @Test @Ignore public void shouldDisplayUnconfiguredMessage() { initializeUI(); } @Test public void shouldDisplayMessageOnConfigurationError() { PortletConfig portletConfig = new PortletConfig(); when(configMock.getPortletConfig()).thenReturn(portletConfig); when( configurationServiceMock.isConfigured(configMock, liferayContext.getPortletPreferencesMock())) .thenReturn(true); when(modelBuilderMock.build()).thenThrow(new RuntimeException("bla")); ArgumentCaptor<Component> components = ArgumentCaptor .forClass(Component.class); initializeUI(); verify(viewPageMock, times(3)).addComponent(components.capture()); // PortletId assertThat(components.getAllValues().get(0), instanceOf(Label.class)); // CommunityId assertThat(components.getAllValues().get(1), instanceOf(Label.class)); assertThat(components.getAllValues().get(2), instanceOf(BusinessExceptionMessage.class)); } @Test public void shouldDisplayPortletViewForExistingConfiguration() { initializeUI(); stubPortletInitialization(); ui.refreshViews(); verify(viewPageMock, never()).addComponent( isA(BusinessExceptionMessage.class)); verify(viewPageMock).addComponent(portletViewMock); } @Test public void shouldUpdatePortletTitleInPreferences() throws ReadOnlyException, ValidatorException, IOException { initializeUI(); stubPortletInitialization(); when(portletMock.getTitle()).thenReturn("newTitle"); ui.refreshViews(); verify(viewPageMock, never()).addComponent( isA(BusinessExceptionMessage.class)); verify(liferayContext.getPortletPreferencesMock()).setValue( CrudVaadinPortlet.PORTLET_TITLE_PREF_KEY, "newTitle"); verify(liferayContext.getPortletPreferencesMock()).store(); } @Test public void shouldNotUpdateUnchangedPortletTitleInPreferences() throws ReadOnlyException, ValidatorException, IOException { initializeUI(); stubPortletInitialization(); when( liferayContext.getPortletPreferencesMock().getValue( CrudVaadinPortlet.PORTLET_TITLE_PREF_KEY, null)) .thenReturn("sameTitle"); when(portletMock.getTitle()).thenReturn("sameTitle"); ui.refreshViews(); verify(viewPageMock, never()).addComponent( isA(BusinessExceptionMessage.class)); verify(liferayContext.getPortletPreferencesMock()).getValue( CrudVaadinPortlet.PORTLET_TITLE_PREF_KEY, null); verify(liferayContext.getPortletPreferencesMock(), never()).store(); } @SuppressWarnings("unchecked") private void stubPortletInitialization() { portletConfig = new PortletConfig(); when( configurationServiceMock.isConfigured(configMock, liferayContext.getPortletPreferencesMock())) .thenReturn(true); when(configMock.getPortletConfig()).thenReturn(portletConfig); when(modelBuilderMock.build()).thenReturn(portletMock); when(guiBuilderMock.build(portletMock)) .thenReturn(portletPresenterMock); when(portletPresenterMock.getView()).thenReturn(portletViewMock); when( scriptModelFactoryMock.getBuilder(any(EventBus.class), any(Portlet.class), any((new HashMap<Object, Object>()).getClass()))) .thenReturn(scriptModelBuilderMock); } @Test public void testHandleResourceRequest() { initializeUI(); expectWindowContentChange(PortletMode.EDIT, ui.getEditContent()); expectWindowContentChange(PortletMode.VIEW, ui.getViewContent()); expectWindowContentChange(PortletMode.HELP, ui.getHelpContent()); } private void expectWindowContentChange(PortletMode targetMode, ComponentContainer expectedContent) { when(liferayContext.getPortletRequestMock().getPortletMode()) .thenReturn(targetMode); callHandleResourceRequest(); assertThat(ui.getContent(), is((Component) expectedContent)); } private void callHandleResourceRequest() { ui.handleResourceRequest( (ResourceRequest) liferayContext.getPortletRequestMock(), (ResourceResponse) liferayContext.getPortletResponseMock(), ui); } @Test public void shouldRefreshEditPageBeforeEntering() { initializeUI(); ui.setPortletDomain(portletMock); when(liferayContext.getPortletRequestMock().getPortletMode()) .thenReturn(PortletMode.VIEW); callHandleResourceRequest(); reset(portletConfigurationPresenterMock); when(liferayContext.getPortletRequestMock().getPortletMode()) .thenReturn(PortletMode.EDIT); callHandleResourceRequest(); verify(portletConfigurationPresenterMock).refresh(configMock); } @Test public void shouldNotRefreshIfAlreadyOnEditPage() { initializeUI(); ui.setPortletDomain(portletMock); when(liferayContext.getPortletRequestMock().getPortletMode()) .thenReturn(PortletMode.EDIT); callHandleResourceRequest(); reset(portletConfigurationPresenterMock); callHandleResourceRequest(); verify(portletConfigurationPresenterMock, never()).refresh( any(Config.class)); } @Test public void shouldRegisterPopupEventHandler() { initializeUI(); verify(eventBusMock).addHandler(ShowPopupEvent.class, ui); } @SuppressWarnings("unchecked") @Test public void shouldProvideInformationIfInitializationIsInProgress() { assertThat(ui.isInitializing(), is(true)); initializeUI(); final PortletConfig portletConfig = new PortletConfig(); when( configurationServiceMock.isConfigured(configMock, liferayContext.getPortletPreferencesMock())) .thenReturn(true); when(configMock.getPortletConfig()).thenAnswer( new Answer<PortletConfig>() { @Override public PortletConfig answer(InvocationOnMock invocation) throws Throwable { assertThat(ui.isInitializing(), is(true)); return portletConfig; } }); when(modelBuilderMock.build()).thenAnswer(new Answer<Portlet>() { @Override public Portlet answer(InvocationOnMock invocation) throws Throwable { assertThat(ui.isInitializing(), is(true)); return portletMock; } }); when(guiBuilderMock.build(portletMock)).thenAnswer( new Answer<PortletPresenter>() { @Override public PortletPresenter answer(InvocationOnMock invocation) throws Throwable { assertThat(ui.isInitializing(), is(true)); return portletPresenterMock; } }); when(portletPresenterMock.getView()).thenReturn(portletViewMock); when( scriptModelFactoryMock.getBuilder(any(EventBus.class), any(Portlet.class), any((Map.class)))).thenAnswer( new Answer<ScriptModelBuilder>() { @Override public ScriptModelBuilder answer(InvocationOnMock invocation) throws Throwable { assertThat(ui.isInitializing(), is(true)); return scriptModelBuilderMock; } }); ui.refreshViews(); verify(viewPageMock).addComponent(portletViewMock); verify(portletMock).handleLoad(); assertThat(ui.isInitializing(), is(false)); } @Test public void shouldInformPortletDomainAboutReloadOnRenderRequest() { initializeUI(); ui.setPortletDomain(portletMock); ui.initializing = false; when(renderRequestMock.getPortletMode()).thenReturn(PortletMode.VIEW); vaadinSession = new VaadinSession(vaadinServiceMock); ui.handleRenderRequest(renderRequestMock, renderResponseMock, ui); verify(portletMock, times(1)).handleReload(); } @Test public void shouldCreateModelPreferencesFromPortletPreferences() { when(liferayContext.getPortletPreferencesMock().getValue("portlet.page.height", null)).thenReturn("fit"); when(liferayContext.getPortletPreferencesMock().getValue("portlet.page.minimum-height", null)).thenReturn("333"); initializeUI(); ModelPreferences prefs = ui.createModelPreferences(); assertThat(prefs.getPageHeight(), is("fit")); assertThat(prefs.getPageMinimumHeight(), is(333)); } @Test public void shouldIgnoreRenderRequestsWithoutSession() { initializeUI(); ui.setPortletDomain(portletMock); ui.initializing = false; vaadinSession = null; when(renderRequestMock.getPortletMode()).thenReturn(PortletMode.VIEW); ui.handleRenderRequest(renderRequestMock, renderResponseMock, ui); verify(portletMock, never()).handleReload(); } @Test public void shouldNotInformPortletDomainAboutReloadIfPortletModeIsNotVIEW() { initializeUI(); ui.setPortletDomain(portletMock); ui.initializing = false; when(renderRequestMock.getPortletMode()).thenReturn(PortletMode.EDIT); vaadinSession = new VaadinSession(vaadinServiceMock); try { ui.handleRenderRequest(renderRequestMock, renderResponseMock, ui); ui.handleRenderRequest(renderRequestMock, renderResponseMock, ui); } catch (Exception e) { // ignore exceptions } verify(portletMock, never()).handleReload(); } @Test public void shouldNotInformPortletDomainAboutReloadOnInitializingRenderRequest() { vaadinSession = new VaadinSession(vaadinServiceMock); ui.handleRenderRequest(renderRequestMock, renderResponseMock, ui); verify(portletMock, never()).handleReload(); } @Test public void shouldValidateConfigurationOnlyInDebugMode(){ when(settingsMock.isDebugMode()).thenReturn(true); stubPortletInitialization(); ModelValidator modelValidatorMock = mock(ModelValidator.class); ui.modelValidator = modelValidatorMock; when(configurationServiceMock.isConfigured(any(Config.class), any(javax.portlet.PortletPreferences.class))).thenReturn(true); when(configurationServiceMock.getPortletConfig(any(String.class), anyLong())).thenReturn(configMock); ui.refreshViews(); verify(modelValidatorMock,times(1)).validateModel(any(ModelBuilder.class), any(Portlet.class), any(PortletConfig.class)); } @Test public void shouldNotValidateConfigurationInProductionMode(){ when(settingsMock.isDebugMode()).thenReturn(false); stubPortletInitialization(); ModelValidator modelValidatorMock = mock(ModelValidator.class); ui.modelValidator = modelValidatorMock; when(configurationServiceMock.isConfigured(any(Config.class), any(javax.portlet.PortletPreferences.class))).thenReturn(true); when(configurationServiceMock.getPortletConfig(any(String.class), anyLong())).thenReturn(configMock); ui.refreshViews(); verify(modelValidatorMock,never()).validateModel(any(ModelBuilder.class), any(Portlet.class), any(PortletConfig.class)); } }