/* * Copyright 2016 Google Inc. * * 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 com.google.cloud.tools.eclipse.appengine.deploy.ui; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import com.google.api.client.auth.oauth2.Credential; import com.google.cloud.tools.eclipse.appengine.deploy.DeployPreferences; import com.google.cloud.tools.eclipse.appengine.deploy.ui.AppEngineDeployPreferencesPanel.ProjectSelectionValidator; import com.google.cloud.tools.eclipse.login.IGoogleLoginService; import com.google.cloud.tools.eclipse.login.ui.AccountSelector; import com.google.cloud.tools.eclipse.login.ui.AccountSelectorObservableValue; import com.google.cloud.tools.eclipse.projectselector.ProjectRepository; import com.google.cloud.tools.eclipse.projectselector.ProjectRepositoryException; import com.google.cloud.tools.eclipse.projectselector.ProjectSelector; import com.google.cloud.tools.eclipse.projectselector.model.GcpProject; import com.google.cloud.tools.eclipse.test.util.ui.CompositeUtil; import com.google.cloud.tools.eclipse.test.util.ui.ShellTestResource; import com.google.cloud.tools.login.Account; import java.util.Arrays; import java.util.HashSet; import org.eclipse.core.databinding.ValidationStatusProvider; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ProjectScope; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swtbot.swt.finder.widgets.SWTBotCheckBox; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.osgi.service.prefs.BackingStoreException; @RunWith(MockitoJUnitRunner.class) public class AppEngineDeployPreferencesPanelTest { private static final String EMAIL_2 = "[email protected]"; private static final String EMAIL_1 = "[email protected]"; private Composite parent; private DeployPreferences model; private AppEngineDeployPreferencesPanel deployPanel; private HashSet<Account> oneAccountSet; private HashSet<Account> twoAccountSet; @Mock private IProject project; @Mock private IGoogleLoginService loginService; @Mock private Runnable layoutChangedHandler; @Mock private Account account1; @Mock private Account account2; @Mock private Credential credential; @Mock private ProjectRepository projectRepository; @Rule public ShellTestResource shellTestResource = new ShellTestResource(); @Before public void setUp() { parent = new Composite(shellTestResource.getShell(), SWT.NONE); when(project.getName()).thenReturn("testProject"); when(account1.getEmail()).thenReturn(EMAIL_1); when(account2.getEmail()).thenReturn(EMAIL_2); when(account1.getOAuth2Credential()).thenReturn(credential); when(account2.getOAuth2Credential()).thenReturn(mock(Credential.class)); oneAccountSet = new HashSet<>(Arrays.asList(account1)); twoAccountSet = new HashSet<>(Arrays.asList(account1, account2)); model = new DeployPreferences(project); } @Test public void testCreateGcpProjectUrl() { assertEquals("https://console.cloud.google.com/projectcreate?previousPage=%2Fprojectselector%2Fappengine%2Fcreate%3Flang%3Djava", AppEngineDeployPreferencesPanel.CREATE_GCP_PROJECT_URL); } @Test public void testAutoSelectSingleAccount() { when(loginService.getAccounts()).thenReturn(oneAccountSet); deployPanel = createPanel(true /* requireValues */); assertThat(deployPanel.getSelectedCredential(), is(credential)); // verify not in error IStatus status = getAccountSelectorValidationStatus(); assertTrue("account selector is in error: " + status.getMessage(), status.isOK()); assertThat("auto-selected value should be propagated back to model", model.getAccountEmail(), is(account1.getEmail())); } @Test public void testAutoSelectSingleAccount_loadGcpProjects() throws ProjectRepositoryException, InterruptedException { when(loginService.getAccounts()).thenReturn(oneAccountSet); initializeProjectRepository(); deployPanel = createPanel(true /* requireValues */); assertNotNull(deployPanel.latestGcpProjectQueryJob); deployPanel.latestGcpProjectQueryJob.join(); assertThat(getProjectSelector().getProjectCount(), is(2)); } @Test public void testValidationMessageWhenNotSignedIn() { deployPanel = createPanel(true /* requireValues */); IStatus status = getAccountSelectorValidationStatus(); assertThat(status.getMessage(), is("Sign in to Google.")); } @Test public void testValidationMessageWhenSignedIn() { // Return two accounts because the account selector will auto-select if there exists only one. when(loginService.getAccounts()).thenReturn(twoAccountSet); deployPanel = createPanel(true /* requireValues */); IStatus status = getAccountSelectorValidationStatus(); assertThat(status.getMessage(), is("Select an account.")); } // https://github.com/GoogleCloudPlatform/google-cloud-eclipse/issues/1229 @Test public void testUncheckStopPreviousVersionButtonWhenDisabled() { deployPanel = createPanel(true /* requireValues */); Button promoteButton = CompositeUtil.findButton(deployPanel, "Promote the deployed version to receive all traffic"); Button stopButton = CompositeUtil.findButton(deployPanel, "Stop previous version"); SWTBotCheckBox promote = new SWTBotCheckBox(promoteButton); SWTBotCheckBox stop = new SWTBotCheckBox(stopButton); // Initially, everything is checked and enabled. assertTrue(promoteButton.getSelection()); assertTrue(stopButton.getSelection()); assertTrue(stopButton.getEnabled()); promote.click(); assertFalse(promoteButton.getSelection()); assertFalse(stopButton.getSelection()); assertFalse(stopButton.getEnabled()); promote.click(); assertTrue(promoteButton.getSelection()); assertTrue(stopButton.getSelection()); assertTrue(stopButton.getEnabled()); stop.click(); assertTrue(promoteButton.getSelection()); assertFalse(stopButton.getSelection()); assertTrue(stopButton.getEnabled()); promote.click(); assertFalse(promoteButton.getSelection()); assertFalse(stopButton.getSelection()); assertFalse(stopButton.getEnabled()); promote.click(); assertTrue(promoteButton.getSelection()); assertFalse(stopButton.getSelection()); assertTrue(stopButton.getEnabled()); } @Test public void testProjectSavedInPreferencesSelected() throws ProjectRepositoryException, InterruptedException, BackingStoreException { IEclipsePreferences node = new ProjectScope(project).getNode(DeployPreferences.PREFERENCE_STORE_QUALIFIER); try { node.put("project.id", "projectId1"); node.put("account.email", EMAIL_1); model = new DeployPreferences(project); initializeProjectRepository(); when(loginService.getAccounts()).thenReturn(twoAccountSet); deployPanel = createPanel(true /* requireValues */); deployPanel.latestGcpProjectQueryJob.join(); ProjectSelector projectSelector = getProjectSelector(); IStructuredSelection selection = projectSelector.getViewer().getStructuredSelection(); assertThat(selection.size(), is(1)); assertThat(((GcpProject) selection.getFirstElement()).getId(), is("projectId1")); } finally { node.clear(); } } private ProjectSelector getProjectSelector() { return CompositeUtil.findControl(deployPanel, ProjectSelector.class); } @Test public void testProjectNotSelectedIsAnErrorWhenRequireValuesIsTrue() { deployPanel = createPanel(true /* requireValues */); assertThat(getProjectSelectionValidator().getSeverity(), is(IStatus.ERROR)); } @Test public void testProjectNotSelectedIsNotAnErrorWhenRequireValuesIsFalse() { deployPanel = createPanel(false /* requireValues */); assertThat(getProjectSelectionValidator().getSeverity(), is(IStatus.INFO)); } @Test public void testProjectsExistThenNoProjectNotFoundError() throws ProjectRepositoryException, InterruptedException { when(loginService.getAccounts()).thenReturn(oneAccountSet); initializeProjectRepository(); deployPanel = createPanel(false /* requireValues */); selectAccount(account1); deployPanel.latestGcpProjectQueryJob.join(); assertThat(getProjectSelectionValidator().getSeverity(), is(IStatus.OK)); } @Test public void testRefreshProjectsForSelectedCredential() throws ProjectRepositoryException, InterruptedException { when(loginService.getAccounts()).thenReturn(twoAccountSet); initializeProjectRepository(); deployPanel = createPanel(false /* requireValues */); assertNull(deployPanel.latestGcpProjectQueryJob); assertThat(getProjectSelector().getProjectCount(), is(0)); selectAccount(account1); assertNotNull(deployPanel.latestGcpProjectQueryJob); deployPanel.latestGcpProjectQueryJob.join(); assertThat(getProjectSelector().getProjectCount(), is(2)); assertThat(getProjectSelector().getProjects().get(0).getId(), is("projectId1")); assertThat(getProjectSelector().getProjects().get(1).getId(), is("projectId2")); } @Test public void testRefreshProjectsForSelectedCredential_switchAccounts() throws ProjectRepositoryException, InterruptedException { when(loginService.getAccounts()).thenReturn(twoAccountSet); initializeProjectRepository(); deployPanel = createPanel(false /* requireValues */); assertNull(deployPanel.latestGcpProjectQueryJob); assertThat(getProjectSelector().getProjectCount(), is(0)); selectAccount(account1); Job jobForAccount1 = deployPanel.latestGcpProjectQueryJob; jobForAccount1.join(); assertThat(getProjectSelector().getProjectCount(), is(2)); selectAccount(account2); assertNotEquals(jobForAccount1, deployPanel.latestGcpProjectQueryJob); deployPanel.latestGcpProjectQueryJob.join(); assertThat(getProjectSelector().getProjectCount(), is(1)); assertThat(getProjectSelector().getProjects().get(0).getId(), is("projectId2")); } // "AppEngineApplicationQueryJob" assumes no project gets selected when switching accounts. @Test public void testNoProjectSelectedWhenSwitchingAccounts() throws ProjectRepositoryException, InterruptedException { when(loginService.getAccounts()).thenReturn(twoAccountSet); initializeProjectRepository(); deployPanel = createPanel(false /* requireValues */); selectAccount(account1); deployPanel.latestGcpProjectQueryJob.join(); assertThat(getProjectSelector().getProjectCount(), is(2)); getProjectSelector() .setSelection(new StructuredSelection(getProjectSelector().getProjects().get(0))); assertThat(getProjectSelector().getSelection().size(), is(1)); selectAccount(account2); deployPanel.latestGcpProjectQueryJob.join(); assertThat(getProjectSelector().getProjectCount(), is(1)); assertThat(getProjectSelector().getSelection().size(), is(0)); } private void selectAccount(Account account) { AccountSelector selector = CompositeUtil.findControl(deployPanel, AccountSelector.class); selector.selectAccount(account.getEmail()); } private AppEngineDeployPreferencesPanel createPanel(boolean requireValues) { return new AppEngineDeployPreferencesPanel(parent, project, loginService, layoutChangedHandler, requireValues, projectRepository, model) { @Override protected String getHelpContextId() { return null; }}; } private IStatus getProjectSelectionValidator() { for (Object object : deployPanel.getDataBindingContext().getValidationStatusProviders()) { if (object instanceof ProjectSelectionValidator) { ProjectSelectionValidator projectSelectionValidator = (ProjectSelectionValidator) object; return (IStatus) projectSelectionValidator.getValidationStatus().getValue(); } } fail("Could not find ProjectSelectionValidator."); return null; } private void initializeProjectRepository() throws ProjectRepositoryException { GcpProject project1 = new GcpProject("Project1", "projectId1"); GcpProject project2 = new GcpProject("Project2", "projectId2"); when(projectRepository.getProjects(any(Credential.class))) .thenReturn(Arrays.asList(project1, project2)) .thenReturn(Arrays.asList(project2)); when(projectRepository.getProject(any(Credential.class), eq("projectId1"))) .thenReturn(project1); when(projectRepository.getProject(any(Credential.class), eq("projectId2"))) .thenReturn(project2); } private IStatus getAccountSelectorValidationStatus() { IStatus status = null; for (Object object : deployPanel.getDataBindingContext().getValidationStatusProviders()) { ValidationStatusProvider statusProvider = (ValidationStatusProvider) object; if (!statusProvider.getTargets().isEmpty()) { if (statusProvider.getTargets().get(0) instanceof AccountSelectorObservableValue) { status = (IStatus) statusProvider.getValidationStatus().getValue(); if (!status.isOK()) { return status; } } } } if (status == null) { fail("Could not find AccountSelector databinding to verify validation"); } return status; } }