// Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See License.txt in the project root. package com.microsoft.alm.plugin.idea.common.ui.settings; import com.google.common.collect.ImmutableList; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.microsoft.alm.core.webapi.model.TeamProjectReference; import com.microsoft.alm.plugin.authentication.AuthHelper; import com.microsoft.alm.plugin.authentication.AuthTypes; import com.microsoft.alm.plugin.authentication.TfsAuthenticationProvider; import com.microsoft.alm.plugin.context.ServerContext; import com.microsoft.alm.plugin.context.ServerContextManager; import com.microsoft.alm.plugin.idea.IdeaAbstractTest; import com.microsoft.alm.plugin.idea.common.resources.TfPluginBundle; import com.microsoft.alm.sourcecontrol.webapi.model.GitRepository; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import javax.swing.Icon; import java.net.URI; import java.util.ArrayList; import java.util.Collections; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; import static org.powermock.api.mockito.PowerMockito.verifyStatic; @RunWith(PowerMockRunner.class) @PrepareForTest({ServerContextManager.class, Messages.class, ProgressManager.class, AuthHelper.class}) public class TeamServicesSettingsModelTest extends IdeaAbstractTest { private TeamServicesSettingsModel teamServicesSettingsModel; @Mock private Project mockProject; @Mock private ServerContextManager mockServerContextManager; @Mock private ServerContext mockServerContext_GitRepo; @Mock private ServerContext mockServerContext_TfvcRepo; @Mock private ServerContext mockServerContext_NoRepo; @Mock private ServerContext mockServerContext_TfsLastUsedUrl; @Mock private GitRepository mockRepo1; @Mock private GitRepository mockRepo_TfsLastUsedUrl; @Mock private TeamProjectReference mockProfRef2; @Mock private ProgressManager mockProgressManager; @Before public void setUp() { MockitoAnnotations.initMocks(this); PowerMockito.mockStatic(ServerContextManager.class, Messages.class, ProgressManager.class, AuthHelper.class); when(mockRepo1.getName()).thenReturn("repo1"); when(mockProfRef2.getName()).thenReturn("repo2"); when(mockRepo_TfsLastUsedUrl.getName()).thenReturn("mockRepo_TfsLastUsedUrl"); when(mockServerContext_GitRepo.getKey()).thenReturn("mockServerContext_GitRepo"); when(mockServerContext_GitRepo.getGitRepository()).thenReturn(mockRepo1); when(mockServerContext_GitRepo.getUri()).thenReturn(URI.create("https://repo1.visualstudio.com")); when(mockServerContext_TfvcRepo.getKey()).thenReturn("mockServerContext_TfvcRepo"); when(mockServerContext_TfvcRepo.getGitRepository()).thenReturn(null); when(mockServerContext_TfvcRepo.getTeamProjectReference()).thenReturn(mockProfRef2); when(mockServerContext_TfvcRepo.getUri()).thenReturn(URI.create("https://repo2.visualstudio.com")); when(mockServerContext_NoRepo.getKey()).thenReturn("mockServerContext_NoRepo"); when(mockServerContext_NoRepo.getGitRepository()).thenReturn(null); when(mockServerContext_TfsLastUsedUrl.getKey()).thenReturn("mockServerContext_TfsLastUsedUrl"); when(mockServerContext_TfsLastUsedUrl.getGitRepository()).thenReturn(mockRepo_TfsLastUsedUrl); when(mockServerContext_TfsLastUsedUrl.getUri()).thenReturn(URI.create(TfsAuthenticationProvider.TFS_LAST_USED_URL)); when(mockServerContextManager.getAllServerContexts()).thenReturn(ImmutableList.of(mockServerContext_GitRepo, mockServerContext_TfvcRepo, mockServerContext_NoRepo, mockServerContext_TfsLastUsedUrl)); when(ServerContextManager.getInstance()).thenReturn(mockServerContextManager); when(ProgressManager.getInstance()).thenReturn(mockProgressManager); teamServicesSettingsModel = new TeamServicesSettingsModel(mockProject); } @Test public void testIsModifiedContexts_True() { teamServicesSettingsModel.setDeleteContexts(ImmutableList.of(mockServerContext_GitRepo)); assertTrue(teamServicesSettingsModel.isModified()); assertEquals(1, teamServicesSettingsModel.getDeleteContexts().size()); } @Test public void testIsModifiedContexts_False() { teamServicesSettingsModel.setDeleteContexts(Collections.EMPTY_LIST); assertFalse(teamServicesSettingsModel.isModified()); assertEquals(0, teamServicesSettingsModel.getDeleteContexts().size()); } @Test public void testIsModifiedAuthType_True() { when(AuthHelper.getAuthTypeInSettingsFile()).thenReturn(AuthTypes.DEVICE_FLOW.name()); teamServicesSettingsModel.setUpdatedAuthType(AuthTypes.CREDS); assertTrue(teamServicesSettingsModel.isModified()); } @Test public void testIsModifiedAuthType_False() { when(AuthHelper.getAuthTypeInSettingsFile()).thenReturn(AuthTypes.DEVICE_FLOW.name()); assertFalse(teamServicesSettingsModel.isModified()); } @Test public void testLoadSettings() { when(AuthHelper.getAuthTypeInSettingsFile()).thenReturn(AuthTypes.DEVICE_FLOW.name()); // running it twice to test we clear contexts teamServicesSettingsModel.loadSettings(); assertEquals(AuthTypes.DEVICE_FLOW, teamServicesSettingsModel.getOriginalAuthType()); assertEquals(2, teamServicesSettingsModel.getTableModel().getRowCount()); assertFalse(teamServicesSettingsModel.isModified()); teamServicesSettingsModel.loadSettings(); assertEquals(AuthTypes.DEVICE_FLOW, teamServicesSettingsModel.getOriginalAuthType()); assertEquals(2, teamServicesSettingsModel.getTableModel().getRowCount()); assertFalse(teamServicesSettingsModel.isModified()); } @Test public void testApply() { when(AuthHelper.getAuthTypeInSettingsFile()).thenReturn(AuthTypes.DEVICE_FLOW.name()); teamServicesSettingsModel.setDeleteContexts(ImmutableList.of(mockServerContext_GitRepo, mockServerContext_TfvcRepo)); teamServicesSettingsModel.setUpdatedAuthType(AuthTypes.CREDS); teamServicesSettingsModel.apply(); assertEquals(0, teamServicesSettingsModel.getTableModel().getRowCount()); assertEquals(0, teamServicesSettingsModel.getDeleteContexts().size()); assertEquals(AuthTypes.CREDS, teamServicesSettingsModel.getOriginalAuthType()); verifyStatic(times(1)); mockServerContextManager.remove("mockServerContext_GitRepo"); mockServerContextManager.remove("mockServerContext_TfvcRepo"); AuthHelper.setDeviceFlowEnvVariableFalse(); } @Test public void testReset() { when(AuthHelper.getAuthTypeInSettingsFile()).thenReturn(AuthTypes.DEVICE_FLOW.name()); teamServicesSettingsModel.setUpdatedAuthType(AuthTypes.CREDS); teamServicesSettingsModel.setDeleteContexts(ImmutableList.of(mockServerContext_GitRepo, mockServerContext_TfvcRepo)); teamServicesSettingsModel.reset(); assertEquals(0, teamServicesSettingsModel.getDeleteContexts().size()); assertEquals(2, teamServicesSettingsModel.getTableModel().getRowCount()); assertFalse(teamServicesSettingsModel.isModified()); } @Test public void testDeletePasswords_OK() { teamServicesSettingsModel.getTableSelectionModel().setSelectionInterval(0, 0); when(Messages.showYesNoDialog(mockProject, TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_DIALOG_DELETE_MSG), TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_DIALOG_DELETE_TITLE), Messages.getQuestionIcon())).thenReturn(Messages.YES); teamServicesSettingsModel.getTableModel().addServerContexts(new ArrayList<ServerContext>(ImmutableList.of(mockServerContext_GitRepo, mockServerContext_TfvcRepo))); teamServicesSettingsModel.deletePasswords(); assertEquals(1, teamServicesSettingsModel.getDeleteContexts().size()); assertEquals(1, teamServicesSettingsModel.getTableModel().getRowCount()); assertEquals(mockServerContext_GitRepo, teamServicesSettingsModel.getTableModel().getServerContext(0)); verifyStatic(times(1)); Messages.showYesNoDialog(eq(mockProject), eq(TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_DIALOG_DELETE_MSG)), eq(TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_DIALOG_DELETE_TITLE)), any(Icon.class)); } @Test public void testDeletePasswords_Cancel() { teamServicesSettingsModel.getTableSelectionModel().setSelectionInterval(0, 0); when(Messages.showYesNoDialog(mockProject, TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_DIALOG_DELETE_MSG), TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_DIALOG_DELETE_TITLE), Messages.getQuestionIcon())).thenReturn(Messages.CANCEL); teamServicesSettingsModel.getTableModel().addServerContexts(new ArrayList<ServerContext>(ImmutableList.of(mockServerContext_GitRepo, mockServerContext_TfvcRepo))); teamServicesSettingsModel.deletePasswords(); assertEquals(0, teamServicesSettingsModel.getDeleteContexts().size()); assertEquals(2, teamServicesSettingsModel.getTableModel().getRowCount()); assertEquals(mockServerContext_TfvcRepo, teamServicesSettingsModel.getTableModel().getServerContext(0)); assertEquals(mockServerContext_GitRepo, teamServicesSettingsModel.getTableModel().getServerContext(1)); verifyStatic(times(1)); Messages.showYesNoDialog(eq(mockProject), eq(TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_DIALOG_DELETE_MSG)), eq(TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_DIALOG_DELETE_TITLE)), any(Icon.class)); } @Test public void testDeletePasswords_NoRowSelected() { teamServicesSettingsModel.getTableModel().addServerContexts(new ArrayList<ServerContext>(ImmutableList.of(mockServerContext_GitRepo, mockServerContext_TfvcRepo))); teamServicesSettingsModel.deletePasswords(); assertEquals(0, teamServicesSettingsModel.getDeleteContexts().size()); assertEquals(2, teamServicesSettingsModel.getTableModel().getRowCount()); assertEquals(mockServerContext_TfvcRepo, teamServicesSettingsModel.getTableModel().getServerContext(0)); assertEquals(mockServerContext_GitRepo, teamServicesSettingsModel.getTableModel().getServerContext(1)); verifyStatic(times(1)); Messages.showWarningDialog(mockProject, TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_NO_ROWS_SELECTED), TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_DIALOG_DELETE_TITLE)); } @Test public void testUpdatePasswords_OK() { teamServicesSettingsModel.getTableSelectionModel().setSelectionInterval(0, 0); when(Messages.showYesNoDialog(mockProject, TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_DIALOG_UPDATE_MSG), TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_DIALOG_UPDATE_TITLE), Messages.getQuestionIcon())).thenReturn(Messages.YES); teamServicesSettingsModel.getTableModel().addServerContexts(new ArrayList<ServerContext>(ImmutableList.of(mockServerContext_GitRepo, mockServerContext_TfvcRepo))); teamServicesSettingsModel.updatePasswords(); assertEquals(0, teamServicesSettingsModel.getDeleteContexts().size()); assertEquals(2, teamServicesSettingsModel.getTableModel().getRowCount()); verifyStatic(times(1)); Messages.showYesNoDialog(eq(mockProject), eq(TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_DIALOG_UPDATE_MSG)), eq(TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_DIALOG_UPDATE_TITLE)), any(Icon.class)); } @Test public void testUpdatePasswords_Cancel() { teamServicesSettingsModel.getTableSelectionModel().setSelectionInterval(0, 0); when(Messages.showYesNoDialog(mockProject, TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_DIALOG_UPDATE_MSG), TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_DIALOG_UPDATE_TITLE), Messages.getQuestionIcon())).thenReturn(Messages.CANCEL); teamServicesSettingsModel.getTableModel().addServerContexts(new ArrayList<ServerContext>(ImmutableList.of(mockServerContext_GitRepo, mockServerContext_TfvcRepo))); teamServicesSettingsModel.updatePasswords(); assertEquals(0, teamServicesSettingsModel.getDeleteContexts().size()); assertEquals(2, teamServicesSettingsModel.getTableModel().getRowCount()); assertEquals(mockServerContext_TfvcRepo, teamServicesSettingsModel.getTableModel().getServerContext(0)); assertEquals(mockServerContext_GitRepo, teamServicesSettingsModel.getTableModel().getServerContext(1)); verifyStatic(times(1)); Messages.showYesNoDialog(eq(mockProject), eq(TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_DIALOG_UPDATE_MSG)), eq(TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_DIALOG_UPDATE_TITLE)), any(Icon.class)); } @Test public void testUpdatePasswords_NoRowSelected() { teamServicesSettingsModel.getTableModel().addServerContexts(new ArrayList<ServerContext>(ImmutableList.of(mockServerContext_GitRepo, mockServerContext_TfvcRepo))); teamServicesSettingsModel.updatePasswords(); assertEquals(0, teamServicesSettingsModel.getDeleteContexts().size()); assertEquals(2, teamServicesSettingsModel.getTableModel().getRowCount()); verifyStatic(times(1)); Messages.showWarningDialog(mockProject, TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_NO_ROWS_SELECTED), TfPluginBundle.message(TfPluginBundle.KEY_SETTINGS_PASSWORD_MGT_DIALOG_UPDATE_TITLE)); } }