/*
* 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.guvnor.structure.client.editors.repository.clone;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.guvnor.structure.client.editors.repository.RepositoryPreferences;
import org.guvnor.structure.client.editors.repository.clone.answer.OuServiceAnswer;
import org.guvnor.structure.client.editors.repository.clone.answer.RsCreateRepositoryAnswer;
import org.guvnor.structure.client.editors.repository.clone.answer.RsCreateRepositoryFailAnswer;
import org.guvnor.structure.client.editors.repository.clone.answer.RsNormalizedNameAnswer;
import org.guvnor.structure.events.AfterCreateOrganizationalUnitEvent;
import org.guvnor.structure.events.AfterDeleteOrganizationalUnitEvent;
import org.guvnor.structure.organizationalunit.OrganizationalUnit;
import org.guvnor.structure.organizationalunit.OrganizationalUnitService;
import org.guvnor.structure.organizationalunit.impl.OrganizationalUnitImpl;
import org.guvnor.structure.repositories.Repository;
import org.guvnor.structure.repositories.RepositoryAlreadyExistsException;
import org.guvnor.structure.repositories.RepositoryEnvironmentConfigurations;
import org.guvnor.structure.repositories.RepositoryService;
import org.guvnor.structure.security.RepositoryFeatures;
import org.gwtbootstrap3.client.ui.constants.ValidationState;
import org.jboss.errai.bus.client.api.messaging.Message;
import org.jboss.errai.common.client.api.Caller;
import org.jboss.errai.common.client.api.ErrorCallback;
import org.jboss.errai.common.client.api.RemoteCallback;
import org.jboss.errai.security.shared.api.Role;
import org.jboss.errai.security.shared.api.RoleImpl;
import org.jboss.errai.security.shared.api.identity.User;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.uberfire.client.mvp.PlaceManager;
import org.uberfire.rpc.SessionInfo;
import org.uberfire.security.authz.AuthorizationManager;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class CloneRepositoryPresenterTest {
private static final String ORG_UNIT_ONE = "OrganizationalUnitOne";
private static final String ORG_UNIT_TWO = "OrganizationalUnitTwo";
private static final String REPO_NAME = "GitRepositoryName";
private static final String REPO_URL = "/home/user/git/url";
private static final String USERNAME = "username";
private static final String PASSWORD = "password";
@Mock
private Message message;
@Mock
private PlaceManager placeManager;
@Mock
private AuthorizationManager authorizationManager;
@Mock
private RepositoryPreferences repositoryPreferences;
@Mock
private CloneRepositoryView view;
@Mock
private Caller<RepositoryService> repoServiceCaller;
@Mock
private Caller<RepositoryService> repoFailServiceCaller;
@Mock
private Caller<OrganizationalUnitService> ouServiceCaller;
@Mock
private OrganizationalUnitService ouService;
@Mock
private RepositoryService repoService;
@Mock
private OrganizationalUnit ouUnit1;
@Mock
private OrganizationalUnit ouUnit2;
@Mock
private Repository repository;
@Mock
private SessionInfo sessionInfo;
@Mock
private User user;
@Captor
private ArgumentCaptor<Boolean> boolArgument;
@Captor
private ArgumentCaptor<Throwable> throwableArgument;
@Captor
private ArgumentCaptor<RepositoryEnvironmentConfigurations> repositoryEnvironmentConfigurationsArgumentCaptor;
private CloneRepositoryPresenter presenter;
@Before
public void initPresenter() {
//mock user roles
Set<Role> userRoles = new HashSet<Role>();
userRoles.add(new RoleImpl("mock-role"));
when(sessionInfo.getIdentity()).thenReturn(user);
when(user.getIdentifier()).thenReturn("mock-user");
when(user.getRoles()).thenReturn(userRoles);
List<OrganizationalUnit> units = new ArrayList<OrganizationalUnit>();
units.add(ouUnit1);
units.add(ouUnit2);
when(ouUnit1.getName()).thenReturn(ORG_UNIT_ONE);
when(ouUnit2.getName()).thenReturn(ORG_UNIT_TWO);
when(view.isNameEmpty()).thenReturn(false);
when(view.getName()).thenReturn(REPO_NAME);
when(view.getSelectedOrganizationalUnit()).thenReturn(ORG_UNIT_ONE);
when(view.getUsername()).thenReturn(USERNAME);
when(view.getPassword()).thenReturn(PASSWORD);
when(ouServiceCaller.call(any(RemoteCallback.class),
any(ErrorCallback.class))).thenAnswer(new OuServiceAnswer(units,
ouService));
when(repoServiceCaller.call(any(RemoteCallback.class))).thenAnswer(new RsNormalizedNameAnswer(REPO_NAME,
repoService));
when(repoServiceCaller.call(any(RemoteCallback.class),
any(ErrorCallback.class))).thenAnswer(new RsCreateRepositoryAnswer(repository,
repoService));
when(repoFailServiceCaller.call(any(RemoteCallback.class))).thenAnswer(new RsNormalizedNameAnswer(REPO_NAME,
repoService));
when(repositoryPreferences.isOUMandatory()).thenReturn(false);
presenter = new CloneRepositoryPresenter(repositoryPreferences,
view,
repoServiceCaller,
ouServiceCaller,
placeManager,
authorizationManager,
sessionInfo);
presenter.init();
}
/**
* BZ 1003005 - Clone repository dialogue stays operational.
* Test if clone repo form doesn't stay operational on valid data in form
*/
@Test
public void testComponentsStaysOperational() {
when(view.isGitUrlEmpty()).thenReturn(false);
when(view.getGitUrl()).thenReturn(REPO_URL);
presenter.handleCloneClick();
componentsLocked();
verifyRepoCloned(true);
}
/**
* Tests if clone repo form is non locked after invalid data filled in form
*/
@Test
public void testComponentsNonLockEmptyUrl() {
when(view.isGitUrlEmpty()).thenReturn(true);
presenter.handleCloneClick();
verify(view).showUrlHelpMandatoryMessage();
componentsNotAffected();
verifyRepoCloned(false);
}
@Test
public void testComponentsNonLockInvalidUrl() {
when(view.isGitUrlEmpty()).thenReturn(false);
when(view.getGitUrl()).thenReturn("git repo");
presenter.handleCloneClick();
verify(view).showUrlHelpInvalidFormatMessage();
componentsNotAffected();
verifyRepoCloned(false);
}
@Test
public void testComponentsNonLockOuMandatory() {
when(view.isGitUrlEmpty()).thenReturn(false);
when(view.getGitUrl()).thenReturn(REPO_URL);
when(view.getSelectedOrganizationalUnit()).thenReturn("non_existing");
when(repositoryPreferences.isOUMandatory()).thenReturn(true);
presenter.handleCloneClick();
verify(view).showOrganizationalUnitHelpMandatoryMessage();
componentsNotAffected();
verifyRepoCloned(false);
}
@Test
public void testComponentsNonLockEmptyName() {
when(view.isGitUrlEmpty()).thenReturn(false);
when(view.getGitUrl()).thenReturn(REPO_URL);
when(view.isNameEmpty()).thenReturn(true);
presenter.handleCloneClick();
verify(view).showNameHelpMandatoryMessage();
componentsNotAffected();
verifyRepoCloned(false);
}
@Test
public void testAlreadyExistClone() {
when(repoFailServiceCaller.call(any(RemoteCallback.class),
any(ErrorCallback.class))).thenAnswer(
new RsCreateRepositoryFailAnswer(message,
new RepositoryAlreadyExistsException(),
repository,
repoService));
presenter = new CloneRepositoryPresenter(repositoryPreferences,
view,
repoFailServiceCaller,
ouServiceCaller,
placeManager,
authorizationManager,
sessionInfo);
presenter.init();
when(view.isGitUrlEmpty()).thenReturn(false);
when(view.getGitUrl()).thenReturn(REPO_URL);
presenter.handleCloneClick();
verify(view).errorRepositoryAlreadyExist();
componentsLocked();
componentsUnlocked();
verifyRepoCloned(false);
}
@Test
public void testFailClone() {
when(view.isGitUrlEmpty()).thenReturn(false);
when(view.getGitUrl()).thenReturn(REPO_URL);
RuntimeException exc = new RuntimeException();
when(repoFailServiceCaller.call(any(RemoteCallback.class),
any(ErrorCallback.class))).thenAnswer(
new RsCreateRepositoryFailAnswer(message,
exc,
repository,
repoService));
presenter = new CloneRepositoryPresenter(repositoryPreferences,
view,
repoFailServiceCaller,
ouServiceCaller,
placeManager,
authorizationManager,
sessionInfo);
presenter.init();
presenter.handleCloneClick();
verify(view).errorCloneRepositoryFail(throwableArgument.capture());
assertEquals(exc,
throwableArgument.getValue());
componentsLocked();
componentsUnlocked();
verifyRepoCloned(false);
}
/**
* BZ 1006906 - Repository clone doesn't validate URL
*/
@Test
public void testGitUrlValidation() {
when(view.isGitUrlEmpty()).thenReturn(false);
when(view.getGitUrl()).thenReturn("a b c");
presenter.handleCloneClick();
when(view.getGitUrl()).thenReturn(":");
presenter.handleCloneClick();
when(view.getGitUrl()).thenReturn("|");
presenter.handleCloneClick();
verify(view,
times(3)).showUrlHelpInvalidFormatMessage();
componentsNotAffected();
verifyRepoCloned(false);
}
/**
* BZ 1006906 - Repository clone doesn't validate URL
* <p/>
* There are two variants of URIUtils class
* At runtime is used javascript version, which consider correctly "abc" as invalid uri
* In tests is used java version, which consider wrongly "abc" as valid uri
*/
@Test
@Ignore("See comments above")
public void testGitUrlValidationSpecial() {
when(view.isGitUrlEmpty()).thenReturn(false);
when(view.getGitUrl()).thenReturn("abc");
presenter.handleCloneClick();
verify(view).showUrlHelpInvalidFormatMessage();
componentsNotAffected();
verifyRepoCloned(false);
}
@Test
public void testCloneNoGroup() {
when(repositoryPreferences.isOUMandatory()).thenReturn(true);
when(view.isGitUrlEmpty()).thenReturn(false);
when(view.getGitUrl()).thenReturn(REPO_URL);
when(view.getName()).thenReturn(REPO_NAME);
when(view.getSelectedOrganizationalUnit()).thenReturn("");
presenter = new CloneRepositoryPresenter(repositoryPreferences,
view,
repoServiceCaller,
ouServiceCaller,
placeManager,
authorizationManager,
sessionInfo);
presenter.handleCloneClick();
verify(view).setOrganizationalUnitGroupType(ValidationState.ERROR);
verify(view).showOrganizationalUnitHelpMandatoryMessage();
verifyRepoCloned(false);
}
@Test
public void testCloneNoUrl() {
when(repositoryPreferences.isOUMandatory()).thenReturn(true);
when(view.isGitUrlEmpty()).thenReturn(true);
when(view.getGitUrl()).thenReturn("");
when(view.getName()).thenReturn(REPO_NAME);
when(view.getSelectedOrganizationalUnit()).thenReturn(ORG_UNIT_ONE);
presenter = new CloneRepositoryPresenter(repositoryPreferences,
view,
repoServiceCaller,
ouServiceCaller,
placeManager,
authorizationManager,
sessionInfo);
presenter.handleCloneClick();
verify(view).setUrlGroupType(ValidationState.ERROR);
verify(view).showUrlHelpMandatoryMessage();
verifyRepoCloned(false);
}
@Test
public void testCancelButton() {
presenter.handleCancelClick();
verify(view).hide();
}
@Test
public void testCreateOUEvent() {
final OrganizationalUnit ou = new OrganizationalUnitImpl("ou1",
"owner1",
"ou");
presenter.onCreateOrganizationalUnit(new AfterCreateOrganizationalUnitEvent(ou));
verify(view,
times(1)).addOrganizationalUnit(ou);
}
@Test
public void testDeleteOUEvent() {
final OrganizationalUnit ou = new OrganizationalUnitImpl("ou1",
"owner1",
"ou");
presenter.onDeleteOrganizationalUnit(new AfterDeleteOrganizationalUnitEvent(ou));
verify(view,
times(1)).deleteOrganizationalUnit(ou);
}
@Test
public void testResetWhenShown() {
presenter.showForm();
verify(view,
times(1)).reset();
}
@Test
public void testCloneManagedRepository() {
when(view.isGitUrlEmpty()).thenReturn(false);
when(repositoryPreferences.isOUMandatory()).thenReturn(false);
when(view.getGitUrl()).thenReturn(REPO_URL);
when(view.getName()).thenReturn(REPO_NAME);
when(view.isManagedRepository()).thenReturn(true);
presenter.handleCloneClick();
verifyRepoCloned(true);
verify(repoService,
times(1)).createRepository(any(OrganizationalUnit.class),
anyString(),
anyString(),
repositoryEnvironmentConfigurationsArgumentCaptor.capture());
final RepositoryEnvironmentConfigurations configurations = repositoryEnvironmentConfigurationsArgumentCaptor.getValue();
assertEquals(USERNAME,
configurations.getUserName());
assertEquals(PASSWORD,
configurations.getPassword());
assertEquals(REPO_URL,
configurations.getOrigin());
assertTrue(configurations.isManaged());
}
@Test
public void testCloneNotManagedRepository() {
when(view.isGitUrlEmpty()).thenReturn(false);
when(repositoryPreferences.isOUMandatory()).thenReturn(false);
when(view.getGitUrl()).thenReturn(REPO_URL);
when(view.getName()).thenReturn(REPO_NAME);
when(view.isManagedRepository()).thenReturn(false);
presenter.handleCloneClick();
verifyRepoCloned(true);
verify(repoService,
times(1)).createRepository(any(OrganizationalUnit.class),
anyString(),
anyString(),
repositoryEnvironmentConfigurationsArgumentCaptor.capture());
final RepositoryEnvironmentConfigurations configurations = repositoryEnvironmentConfigurationsArgumentCaptor.getValue();
assertEquals(USERNAME,
configurations.getUserName());
assertEquals(PASSWORD,
configurations.getPassword());
assertEquals(REPO_URL,
configurations.getOrigin());
assertFalse(configurations.isManaged());
}
@Test
public void testManagedRepositoryIsEnabledInCloneRepoDialog() {
reset(view);
when(authorizationManager.authorize(RepositoryFeatures.CONFIGURE_REPOSITORY,
sessionInfo.getIdentity())).thenReturn(true);
presenter.init();
verify(view).enableManagedRepoCreation(true);
verify(view,
never()).enableManagedRepoCreation(false);
}
@Test
public void testManagedRepositoryIsDisabledInCloneRepoDialog() {
reset(view);
when(authorizationManager.authorize(RepositoryFeatures.CONFIGURE_REPOSITORY,
sessionInfo.getIdentity())).thenReturn(false);
presenter.init();
verify(view,
never()).enableManagedRepoCreation(true);
verify(view).enableManagedRepoCreation(false);
}
private void componentsNotAffected() {
verify(view,
never()).setCloneEnabled(anyBoolean());
verify(view,
never()).setGitUrlEnabled(anyBoolean());
verify(view,
never()).setNameEnabled(anyBoolean());
verify(view,
never()).setOrganizationalUnitEnabled(anyBoolean());
verify(view,
never()).setUsernameEnabled(anyBoolean());
verify(view,
never()).setPasswordEnabled(anyBoolean());
verify(view,
never()).showBusyPopupMessage();
verify(view,
never()).closeBusyPopup();
}
private void componentsLocked() {
verify(view).showBusyPopupMessage();
verify(view).setCloneEnabled(false);
verify(view).setGitUrlEnabled(false);
verify(view).setNameEnabled(false);
verify(view).setOrganizationalUnitEnabled(false);
verify(view).setUsernameEnabled(false);
verify(view).setPasswordEnabled(false);
}
private void componentsUnlocked() {
verify(view).closeBusyPopup();
verify(view).setCloneEnabled(true);
verify(view).setGitUrlEnabled(true);
verify(view).setNameEnabled(true);
verify(view).setOrganizationalUnitEnabled(true);
verify(view).setUsernameEnabled(true);
verify(view).setPasswordEnabled(true);
}
private void verifyRepoCloned(boolean cloned) {
if (cloned) {
verify(view).alertRepositoryCloned();
verify(view).hide();
} else {
verify(view,
never()).alertRepositoryCloned();
verify(view,
never()).hide();
}
}
}