| /******************************************************************************* |
| * Copyright (c) 2010, 2019 SAP AG and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Mathias Kinzler (SAP AG) - initial implementation |
| * Tobias Baumann <tobbaumann@gmail.com> - Bug #494269 |
| *******************************************************************************/ |
| package org.eclipse.egit.ui.view.repositories; |
| |
| import static org.eclipse.swtbot.swt.finder.waits.Conditions.shellCloses; |
| import static org.hamcrest.CoreMatchers.not; |
| import static org.hamcrest.MatcherAssert.assertThat; |
| import static org.hamcrest.Matchers.hasItem; |
| import static org.junit.Assert.assertArrayEquals; |
| 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.assertTrue; |
| |
| import java.io.File; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.Adapters; |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.egit.core.RepositoryUtil; |
| import org.eclipse.egit.core.op.StashCreateOperation; |
| import org.eclipse.egit.core.project.RepositoryMapping; |
| import org.eclipse.egit.ui.Activator; |
| import org.eclipse.egit.ui.JobFamilies; |
| import org.eclipse.egit.ui.UIPreferences; |
| import org.eclipse.egit.ui.common.StagingViewTester; |
| import org.eclipse.egit.ui.internal.UIText; |
| import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNode; |
| import org.eclipse.egit.ui.internal.repository.tree.StashedCommitNode; |
| import org.eclipse.egit.ui.test.ContextMenuHelper; |
| import org.eclipse.egit.ui.test.TestUtil; |
| import org.eclipse.jface.dialogs.IDialogConstants; |
| import org.eclipse.jgit.lib.Constants; |
| import org.eclipse.jgit.lib.Repository; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; |
| import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner; |
| import org.eclipse.swtbot.swt.finder.utils.TableCollection; |
| import org.eclipse.swtbot.swt.finder.waits.Conditions; |
| import org.eclipse.swtbot.swt.finder.waits.DefaultCondition; |
| import org.eclipse.swtbot.swt.finder.widgets.SWTBotButton; |
| import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell; |
| import org.eclipse.swtbot.swt.finder.widgets.SWTBotText; |
| import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree; |
| import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem; |
| import org.eclipse.ui.IPageLayout; |
| import org.eclipse.ui.IWorkingSet; |
| import org.eclipse.ui.IWorkingSetManager; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.internal.dialogs.WorkbenchWizardElement; |
| import org.eclipse.ui.internal.wizards.AbstractExtensionWizardRegistry; |
| import org.eclipse.ui.wizards.IWizardCategory; |
| import org.eclipse.ui.wizards.IWizardDescriptor; |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| /** |
| * SWTBot Tests for the Git Repositories View. |
| * |
| * <pre> |
| * TODO |
| * global copy and paste command |
| * bare repository support including copy of path from workdir |
| * copy path from file and folder |
| * paste with empty and invalid path |
| * create branch with selection not on a ref |
| * tags altogether |
| * fetch and push to configured remote |
| * import wizard outside the "golden path" |
| * </pre> |
| */ |
| @RunWith(SWTBotJunit4ClassRunner.class) |
| public class GitRepositoriesViewTest extends GitRepositoriesViewTestBase { |
| |
| private File repositoryFile; |
| |
| private boolean initialLinkingState; |
| |
| @Before |
| public void prepare() throws Exception { |
| setVerboseBranchMode(false); |
| initialLinkingState = setLinkWithSelection(false); |
| repositoryFile = createProjectAndCommitToRepository(); |
| RepositoryUtil.INSTANCE.addConfiguredRepository(repositoryFile); |
| } |
| |
| @After |
| public void resetLinkingState() { |
| setLinkWithSelection(initialLinkingState); |
| } |
| |
| /** |
| * First level should have 5 children |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testExpandFirstLevel() throws Exception { |
| SWTBotTree tree = getOrOpenView().bot().tree(); |
| SWTBotTreeItem item = TestUtil.expandAndWait( |
| myRepoViewUtil.getRootItem(tree, repositoryFile)); |
| SWTBotTreeItem[] children = item.getItems(); |
| assertEquals("Wrong number of children", 5, children.length); |
| } |
| |
| /** |
| * Tests that the tree does not suddenly have a node with a null repository. |
| * |
| * @throws Exception |
| * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=552622">bug |
| * 552622</a> |
| */ |
| @Test |
| public void testWithStagingView() throws Exception { |
| // Fails consistently on Mac without the fix from bug 552622 and |
| // succeeds with that fix. On Jenkins this test never failed?! |
| SWTBotTree tree = getOrOpenView().bot().tree(); |
| StagingViewTester stagingViewTester = StagingViewTester |
| .openStagingView(); |
| TestUtil.waitForDecorations(); |
| SWTBotTreeItem item = myRepoViewUtil.getRootItem(tree, repositoryFile); |
| item.select(); |
| TestUtil.waitForDecorations(); |
| stagingViewTester.getView().close(); |
| TestUtil.waitForDecorations(); |
| SWTBotTreeItem[] items = tree.getAllItems(); |
| boolean[] hasNull = { false }; |
| String[] unknownClass = { "" }; |
| tree.widget.getDisplay().syncExec(() -> { |
| for (SWTBotTreeItem i : items) { |
| Object obj = i.widget.getData(); |
| if (!(obj instanceof RepositoryTreeNode)) { |
| unknownClass[0] = obj.getClass().getName(); |
| break; |
| } |
| if (((RepositoryTreeNode) obj).getRepository() == null) { |
| hasNull[0] = true; |
| break; |
| } |
| } |
| }); |
| assertEquals("Unknown tree element", "", unknownClass[0]); |
| assertFalse("Tree has node with null repository", hasNull[0]); |
| } |
| |
| /** |
| * Open (expand, file->editor, branch->checkout) |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testOpen() throws Exception { |
| // expand first level |
| SWTBotTree tree = getOrOpenView().bot().tree(); |
| SWTBotTreeItem item = myRepoViewUtil.getRootItem(tree, repositoryFile); |
| item.collapse(); |
| refreshAndWait(); |
| item = myRepoViewUtil.getRootItem(tree, repositoryFile); |
| assertTrue("Item should not be expanded", !item.isExpanded()); |
| item.doubleClick(); |
| assertTrue("Item should be expanded", item.isExpanded()); |
| // open a file in editor |
| item = TestUtil.expandAndWait( |
| myRepoViewUtil.getWorkdirItem(tree, repositoryFile)); |
| SWTBotTreeItem fileiItem = TestUtil.expandAndWait(item.getNode(PROJ1)) |
| .getNode(FOLDER); |
| fileiItem = TestUtil.expandAndWait(fileiItem).getNode(FILE1).select(); |
| fileiItem.doubleClick(); |
| assertTrue(bot.activeEditor().getTitle().equals(FILE1)); |
| bot.activeEditor().close(); |
| refreshAndWait(); |
| |
| // opening current branch is a no-op |
| String contentMaster = getTestFileContent(); |
| // open a branch (checkout) |
| checkoutWithDoubleClick(tree, "stable"); |
| String contentStable = getTestFileContent(); |
| assertNotEquals("Content of master and stable should differ", |
| contentMaster, contentStable); |
| } |
| |
| private void checkoutWithDoubleClick(SWTBotTree tree, String branch) |
| throws Exception { |
| SWTBotTreeItem node = myRepoViewUtil.getLocalBranchesItem(tree, |
| repositoryFile); |
| TestUtil.expandAndWait(node).getNode(branch).doubleClick(); |
| SWTBotShell shell = bot |
| .shell(UIText.RepositoriesView_CheckoutConfirmationTitle); |
| shell.bot() |
| .button(UIText.RepositoriesView_CheckoutConfirmationDefaultButtonLabel) |
| .click(); |
| TestUtil.joinJobs(JobFamilies.CHECKOUT); |
| refreshAndWait(); |
| } |
| |
| /** |
| * Checks for the Symbolic Reference node |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testExpandSymbolicRef() throws Exception { |
| SWTBotTree tree = getOrOpenView().bot().tree(); |
| SWTBotTreeItem item = TestUtil.expandAndWait( |
| myRepoViewUtil.getSymbolicRefsItem(tree, repositoryFile)); |
| List<String> children = item.getNodes(); |
| boolean found = false; |
| for (String child : children) { |
| if (child.contains(Constants.HEAD)) { |
| found = true; |
| break; |
| } |
| } |
| assertTrue(found); |
| } |
| |
| /** |
| * Checks the first level of the working directory |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testExpandWorkDir() throws Exception { |
| SWTBotTree tree = getOrOpenView().bot().tree(); |
| Repository myRepository = lookupRepository(repositoryFile); |
| List<String> children = Arrays |
| .asList(myRepository.getWorkTree().list()); |
| List<String> treeChildren = TestUtil |
| .expandAndWait( |
| myRepoViewUtil.getWorkdirItem(tree, repositoryFile)) |
| .getNodes(); |
| assertTrue(children.containsAll(treeChildren) |
| && treeChildren.containsAll(children)); |
| SWTBotTreeItem item = TestUtil.expandAndWait( |
| myRepoViewUtil.getWorkdirItem(tree, repositoryFile)); |
| item = TestUtil.expandAndWait(item.getNode(PROJ1)); |
| item = TestUtil.expandAndWait(item.getNode(FOLDER)); |
| item.getNode(FILE1); |
| } |
| |
| /** |
| * Checks is some context menus are available, should be replaced with real |
| * tests |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testContextMenuRepository() throws Exception { |
| removeSmartImportWizardToForceGitImportWizardUsage(); |
| Activator.getDefault().getPreferenceStore() |
| .setValue(UIPreferences.ALWAYS_USE_STAGING_VIEW, false); |
| // We just check if the dialogs open, the actual commit and import |
| // projects |
| // is tested elsewhere |
| SWTBotTree tree = getOrOpenView().bot().tree(); |
| SWTBotTreeItem item = myRepoViewUtil.getRootItem(tree, repositoryFile); |
| item.select(); |
| assertClickOpens(tree, |
| myUtil.getPluginLocalizedValue("RepoViewCommit.label"), |
| UIText.CommitDialog_CommitChanges); |
| assertClickOpens(tree, |
| myUtil.getPluginLocalizedValue("RepoViewImportProjects.label"), |
| NLS.bind(UIText.GitCreateProjectViaWizardWizard_WizardTitle, |
| repositoryFile)); |
| Activator.getDefault().getPreferenceStore() |
| .setValue(UIPreferences.ALWAYS_USE_STAGING_VIEW, true); |
| } |
| |
| /** |
| * Show properties |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testShowProperties() throws Exception { |
| SWTBotTree tree = getOrOpenView().bot().tree(); |
| SWTBotTreeItem item = myRepoViewUtil.getRootItem(tree, repositoryFile); |
| item.select(); |
| ContextMenuHelper.clickContextMenuSync(tree, |
| myUtil.getPluginLocalizedValue("ShowIn"), "Properties"); |
| SWTBotView propertieView = bot.viewById(IPageLayout.ID_PROP_SHEET); |
| assertTrue(propertieView.isActive()); |
| } |
| |
| /** |
| * Import wizard golden path test |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testImportWizard() throws Exception { |
| removeSmartImportWizardToForceGitImportWizardUsage(); |
| deleteAllProjects(); |
| assertProjectExistence(PROJ1, false); |
| SWTBotTree tree = getOrOpenView().bot().tree(); |
| SWTBotTreeItem item = myRepoViewUtil.getRootItem(tree, repositoryFile); |
| String wizardTitle = NLS.bind( |
| UIText.GitCreateProjectViaWizardWizard_WizardTitle, |
| repositoryFile.getPath()); |
| |
| // start wizard from root item |
| item.select(); |
| ContextMenuHelper.clickContextMenu(tree, |
| myUtil.getPluginLocalizedValue("ImportProjectsCommand")); |
| SWTBotShell shell = bot.shell(wizardTitle); |
| bot.radio(UIText.GitSelectWizardPage_ImportExistingButton).click(); |
| TableCollection selected = shell.bot().tree().selection(); |
| String wizardNodeText = selected.get(0, 0); |
| // wizard directory should be working dir |
| String expected = myRepoViewUtil.getWorkdirItem(tree, repositoryFile) |
| .getText(); |
| // One or the other or both or none might contain decorations |
| assertTrue(expected.contains(wizardNodeText) |
| || wizardNodeText.contains(expected)); |
| shell.close(); |
| tree = getOrOpenView().bot().tree(); |
| // start wizard from .git |
| TestUtil.expandAndWait( |
| myRepoViewUtil.getWorkdirItem(tree, repositoryFile)) |
| .getNode(Constants.DOT_GIT).select(); |
| ContextMenuHelper.clickContextMenu(tree, |
| myUtil.getPluginLocalizedValue("ImportProjectsCommand")); |
| shell = bot.shell(wizardTitle); |
| selected = shell.bot().tree().selection(); |
| wizardNodeText = selected.get(0, 0); |
| // wizard directory should be .git |
| assertEquals(Constants.DOT_GIT, wizardNodeText); |
| shell.bot().button(IDialogConstants.NEXT_LABEL).click(); |
| shell.bot().label("Import Projects"); // wait for import projects page |
| assertEquals(0, shell.bot().tree().getAllItems().length); |
| shell.bot().button(IDialogConstants.BACK_LABEL).click(); |
| // go to project with .project |
| shell.bot().tree().getAllItems()[0].getNode(PROJ1).select(); |
| // next is 1 |
| shell.bot().button(IDialogConstants.NEXT_LABEL).click(); |
| bot.button(UIText.WizardProjectsImportPage_deselectAll).click(); |
| assertEquals(1, shell.bot().tree().getAllItems().length); |
| assertTrue( |
| !shell.bot().button(IDialogConstants.FINISH_LABEL).isEnabled()); |
| shell.bot().button(UIText.WizardProjectsImportPage_selectAll).click(); |
| assertTrue( |
| shell.bot().button(IDialogConstants.FINISH_LABEL).isEnabled()); |
| shell.bot().button(IDialogConstants.FINISH_LABEL).click(); |
| bot.waitUntil(Conditions.shellCloses(shell)); |
| assertProjectExistence(PROJ1, true); |
| assertProjectIsShared(PROJ1, true); |
| } |
| |
| private static void removeSmartImportWizardToForceGitImportWizardUsage() |
| throws Exception { |
| final String smartImportWizardId = "org.eclipse.e4.ui.importer.wizard"; |
| AbstractExtensionWizardRegistry wizardRegistry = (AbstractExtensionWizardRegistry) PlatformUI |
| .getWorkbench().getImportWizardRegistry(); |
| IWizardCategory[] categories = PlatformUI.getWorkbench() |
| .getImportWizardRegistry().getRootCategory().getCategories(); |
| for (IWizardDescriptor wizard : getAllWizards(categories)) { |
| if (wizard.getId().equals(smartImportWizardId)) { |
| WorkbenchWizardElement wizardElement = (WorkbenchWizardElement) wizard; |
| wizardRegistry.removeExtension( |
| wizardElement.getConfigurationElement() |
| .getDeclaringExtension(), |
| new Object[] { wizardElement }); |
| return; |
| } |
| } |
| } |
| |
| private static IWizardDescriptor[] getAllWizards( |
| IWizardCategory[] categories) { |
| List<IWizardDescriptor> results = new ArrayList<>(); |
| for (IWizardCategory wizardCategory : categories) { |
| results.addAll(Arrays.asList(wizardCategory.getWizards())); |
| results.addAll(Arrays |
| .asList(getAllWizards(wizardCategory.getCategories()))); |
| } |
| return results.toArray(new IWizardDescriptor[0]); |
| } |
| |
| @Test |
| public void testImportWizardGeneralProject() throws Exception { |
| removeSmartImportWizardToForceGitImportWizardUsage(); |
| deleteAllProjects(); |
| assertProjectExistence(PROJ2, false); |
| SWTBotTree tree = getOrOpenView().bot().tree(); |
| String wizardTitle = NLS.bind( |
| UIText.GitCreateProjectViaWizardWizard_WizardTitle, |
| repositoryFile.getPath()); |
| // start wizard from PROJ2 |
| TestUtil.expandAndWait( |
| myRepoViewUtil.getWorkdirItem(tree, repositoryFile)) |
| .getNode(PROJ2).select(); |
| ContextMenuHelper.clickContextMenu(tree, |
| myUtil.getPluginLocalizedValue("ImportProjectsCommand")); |
| SWTBotShell shell = bot.shell(wizardTitle); |
| shell = bot.shell(wizardTitle); |
| // try import existing project first |
| bot.radio(UIText.GitSelectWizardPage_ImportExistingButton).click(); |
| TableCollection selected = shell.bot().tree().selection(); |
| String wizardNode = selected.get(0, 0); |
| // wizard directory should be PROJ2 |
| assertEquals(PROJ2, wizardNode); |
| shell.bot().button(IDialogConstants.NEXT_LABEL).click(); |
| assertWizardDialogMessage(shell.bot(), |
| " " + UIText.GitProjectsImportPage_NoProjectsMessage); |
| assertEquals(0, shell.bot().tree().getAllItems().length); |
| shell.bot().button(IDialogConstants.BACK_LABEL).click(); |
| // import as general |
| shell.bot().radio(UIText.GitSelectWizardPage_ImportAsGeneralButton) |
| .click(); |
| shell.bot().button(IDialogConstants.NEXT_LABEL).click(); |
| assertEquals(PROJ2, |
| shell.bot() |
| .textWithLabel( |
| UIText.GitCreateGeneralProjectPage_ProjectNameLabel) |
| .getText()); |
| // switch to a sub directory and see if this is used |
| shell.bot().button(IDialogConstants.BACK_LABEL).click(); |
| SWTBotTreeItem item = TestUtil |
| .expandAndWait(shell.bot().tree().getAllItems()[0]); |
| TestUtil.expandAndWait(item.getNode(PROJ2)).getNode(FOLDER).select(); |
| shell.bot().button(IDialogConstants.NEXT_LABEL).click(); |
| String name = shell.bot() |
| .textWithLabel( |
| UIText.GitCreateGeneralProjectPage_ProjectNameLabel) |
| .getText(); |
| assertEquals(FOLDER, name); |
| shell.bot().button(IDialogConstants.BACK_LABEL).click(); |
| // switch back to the root directory |
| TestUtil.expandAndWait(shell.bot().tree().getAllItems()[0]) |
| .getNode(PROJ2).select(); |
| shell.bot().button(IDialogConstants.NEXT_LABEL).click(); |
| assertEquals(PROJ2, |
| shell.bot() |
| .textWithLabel( |
| UIText.GitCreateGeneralProjectPage_ProjectNameLabel) |
| .getText()); |
| |
| shell.bot().button(IDialogConstants.FINISH_LABEL).click(); |
| bot.waitUntil(Conditions.shellCloses(shell)); |
| assertProjectExistence(PROJ2, true); |
| assertProjectIsShared(PROJ2, true); |
| } |
| |
| @Test |
| public void testImportWizardGeneralProjectWithWorkingSet() |
| throws Exception { |
| removeSmartImportWizardToForceGitImportWizardUsage(); |
| deleteAllProjects(); |
| assertProjectExistence(PROJ1, false); |
| String workingSetName = "myWorkingSet"; |
| removeWorkingSet(workingSetName); |
| SWTBotTree tree = getOrOpenView().bot().tree(); |
| String wizardTitle = NLS.bind( |
| UIText.GitCreateProjectViaWizardWizard_WizardTitle, |
| repositoryFile.getPath()); |
| // start wizard from PROJ1 |
| TestUtil.expandAndWait( |
| myRepoViewUtil.getWorkdirItem(tree, repositoryFile)) |
| .getNode(PROJ1).select(); |
| ContextMenuHelper.clickContextMenu(tree, |
| myUtil.getPluginLocalizedValue("ImportProjectsCommand")); |
| SWTBotShell shell = bot.shell(wizardTitle); |
| shell = bot.shell(wizardTitle); |
| // try import existing project first |
| bot.radio(UIText.GitSelectWizardPage_ImportExistingButton).click(); |
| SWTBotButton button = shell.bot().button(IDialogConstants.NEXT_LABEL); |
| // Set focus on the next button. If this is not done, Wizard Framework |
| // restores |
| // the focus to the "Import as &General Project" radio button. Setting |
| // the focus on |
| // the radio button selects the button and causes the test to fail. |
| // See also SWTBot Bug 337465 |
| button.setFocus(); |
| button.click(); |
| assertWizardDialogMessage(shell.bot(), |
| UIText.WizardProjectsImportPage_ImportProjectsDescription); |
| shell.bot().tree().getAllItems()[0].check(); |
| // add to working set |
| shell.bot().checkBox("Add project to working sets").select(); |
| // create new working set |
| shell.bot().button("Select...").click(); |
| SWTBotShell workingSetDialog = bot.shell("Select Working Sets"); |
| workingSetDialog.bot().button("New...").click(); |
| SWTBotShell newDialog = bot.shell("New Working Set"); |
| newDialog.bot().table().select("Java"); |
| newDialog.bot().button(IDialogConstants.NEXT_LABEL).click(); |
| newDialog.bot().text(0).setText(workingSetName); |
| newDialog.bot().button(IDialogConstants.FINISH_LABEL).click(); |
| workingSetDialog.bot().table().getTableItem(workingSetName).check(); |
| workingSetDialog.bot().button(IDialogConstants.OK_LABEL).click(); |
| shell.bot().button(IDialogConstants.FINISH_LABEL).click(); |
| bot.waitUntil(Conditions.shellCloses(shell)); |
| assertProjectExistence(PROJ1, true); |
| assertProjectInWorkingSet(workingSetName, PROJ1); |
| assertProjectIsShared(PROJ1, true); |
| removeWorkingSet(workingSetName); |
| } |
| |
| private void assertProjectInWorkingSet(String workingSetName, |
| String projectName) { |
| IWorkingSetManager workingSetManager = PlatformUI.getWorkbench() |
| .getWorkingSetManager(); |
| IWorkingSet workingSet = workingSetManager |
| .getWorkingSet(workingSetName); |
| IAdaptable[] elements = workingSet.getElements(); |
| assertEquals("Wrong number of projects in working set", 1, |
| elements.length); |
| IProject project = Adapters.adapt(elements[0], IProject.class); |
| assertEquals("Wrong project in working set", projectName, |
| project.getName()); |
| } |
| |
| private void removeWorkingSet(String name) { |
| IWorkingSetManager workingSetManager = PlatformUI.getWorkbench() |
| .getWorkingSetManager(); |
| IWorkingSet workingSet = workingSetManager.getWorkingSet(name); |
| if (workingSet != null) |
| workingSetManager.removeWorkingSet(workingSet); |
| } |
| |
| private void assertProjectIsShared(String projectName, |
| boolean shouldBeShared) { |
| IProject project = ResourcesPlugin.getWorkspace().getRoot() |
| .getProject(projectName); |
| RepositoryMapping mapping = RepositoryMapping.getMapping(project); |
| if (shouldBeShared) { |
| assertNotNull(mapping); |
| assertNotNull(mapping.getRepository()); |
| } else |
| assertNull(mapping); |
| } |
| |
| @Test |
| public void testLinkWithSelectionNavigator() throws Exception { |
| deleteAllProjects(); |
| shareProjects(repositoryFile); |
| SWTBotTree tree = getOrOpenView().bot().tree(); |
| myRepoViewUtil.getRootItem(tree, repositoryFile).select(); |
| // the selection should be root |
| assertTrue(tree.selection().get(0, 0).contains(REPO1)); |
| |
| SWTBotTree projectExplorerTree = TestUtil.getExplorerTree(); |
| getProjectItem(projectExplorerTree, PROJ1).select(); |
| |
| // the selection should be still be root |
| assertTrue(tree.selection().get(0, 0).contains(REPO1)); |
| |
| // activate the link with selection |
| toggleLinkWithSelection(); |
| |
| // the selection should be project |
| assertTrue(tree.selection().get(0, 0).equals(PROJ1)); |
| } |
| |
| /** |
| * Link with editor, both ways |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testLinkWithSelectionEditor() throws Exception { |
| deleteAllProjects(); |
| shareProjects(repositoryFile); |
| SWTBotTree tree = getOrOpenView().bot().tree(); |
| myRepoViewUtil.getRootItem(tree, repositoryFile).select(); |
| // the selection should be root |
| assertTrue(tree.selection().get(0, 0).startsWith(REPO1)); |
| |
| SWTBotView view = TestUtil.showExplorerView(); |
| SWTBotTree projectExplorerTree = view.bot().tree(); |
| |
| SWTBotTreeItem item = TestUtil |
| .expandAndWait(getProjectItem(projectExplorerTree, PROJ1)); |
| item = TestUtil.expandAndWait(item.getNode(FOLDER)).getNode(FILE1); |
| view.show(); |
| item.doubleClick(); |
| |
| item = TestUtil |
| .expandAndWait(getProjectItem(projectExplorerTree, PROJ1)); |
| item = TestUtil.expandAndWait(item.getNode(FOLDER)).getNode(FILE2); |
| view.show(); |
| item.doubleClick(); |
| // now we should have two editors |
| |
| // the selection should be still be root |
| assertTrue(tree.selection().get(0, 0).startsWith(REPO1)); |
| |
| // activate the link with selection |
| toggleLinkWithSelection(); |
| |
| bot.editorByTitle(FILE2).show(); |
| // the selection should have changed to the latest editor |
| TestUtil.waitUntilTreeHasSelectedNodeWithText(bot, tree, FILE2, 10000); |
| |
| bot.editorByTitle(FILE1).show(); |
| // selection should have changed |
| TestUtil.waitUntilTreeHasSelectedNodeWithText(bot, tree, FILE1, 10000); |
| |
| // deactivate the link with editor |
| toggleLinkWithSelection(); |
| |
| bot.editorByTitle(FILE2).show(); |
| // the selection should be still be test.txt |
| TestUtil.waitUntilTreeHasSelectedNodeWithText(bot, tree, FILE1, 10000); |
| |
| bot.editorByTitle(FILE1).show(); |
| |
| item = TestUtil.expandAndWait( |
| myRepoViewUtil.getWorkdirItem(tree, repositoryFile)); |
| item = TestUtil.expandAndWait(item.getNode(PROJ1)); |
| item = TestUtil.expandAndWait(item.getNode(FOLDER)); |
| item.getNode(FILE2).select(); |
| |
| // the editor should still be test.txt |
| assertEquals(FILE1, bot.activeEditor().getTitle()); |
| |
| // activate again |
| toggleLinkWithSelection(); |
| |
| item = TestUtil.expandAndWait( |
| myRepoViewUtil.getWorkdirItem(tree, repositoryFile)); |
| item = TestUtil.expandAndWait(item.getNode(PROJ1)); |
| item = TestUtil.expandAndWait(item.getNode(FOLDER)); |
| item.getNode(FILE2).select(); |
| TestUtil.waitUntilEditorIsActive(bot, bot.editorByTitle(FILE2), 10000); |
| |
| item = TestUtil.expandAndWait( |
| myRepoViewUtil.getWorkdirItem(tree, repositoryFile)); |
| item = TestUtil.expandAndWait(item.getNode(PROJ1)); |
| item = TestUtil.expandAndWait(item.getNode(FOLDER)); |
| item.getNode(FILE1).select(); |
| TestUtil.waitUntilEditorIsActive(bot, bot.editorByTitle(FILE1), 10000); |
| |
| // deactivate the link with editor |
| toggleLinkWithSelection(); |
| |
| item = TestUtil.expandAndWait( |
| myRepoViewUtil.getWorkdirItem(tree, repositoryFile)); |
| item = TestUtil.expandAndWait(item.getNode(PROJ1)); |
| item = TestUtil.expandAndWait(item.getNode(FOLDER)); |
| item.getNode(FILE2).select(); |
| TestUtil.waitUntilEditorIsActive(bot, bot.editorByTitle(FILE1), 10000); |
| } |
| |
| @Test |
| public void testDeleteSingleBranch() throws Exception { |
| // expand first level |
| SWTBotTree tree = getOrOpenView().bot().tree(); |
| refreshAndWait(); |
| // create a branch (no checkout) |
| SWTBotTreeItem localBranchesItem = TestUtil.expandAndWait( |
| myRepoViewUtil.getLocalBranchesItem(tree, repositoryFile)); |
| SWTBotTreeItem masterNode = localBranchesItem.getNode("master"); |
| masterNode.select(); |
| ContextMenuHelper.clickContextMenu(tree, |
| myUtil.getPluginLocalizedValue("RepoViewCreateBranch.label")); |
| SWTBotShell createBranchShell = bot |
| .shell(UIText.CreateBranchWizard_NewBranchTitle); |
| createBranchShell.bot().textWithId("BranchName").setText("abc"); |
| createBranchShell.bot().checkBox(UIText.CreateBranchPage_CheckoutButton) |
| .deselect(); |
| createBranchShell.bot().button(IDialogConstants.FINISH_LABEL).click(); |
| bot.waitUntil(shellCloses(createBranchShell), 10000); |
| refreshAndWait(); |
| // delete branch |
| // lookup node again. Widget might have changed due to refresh |
| localBranchesItem = TestUtil.expandAndWait( |
| myRepoViewUtil.getLocalBranchesItem(tree, repositoryFile)); |
| localBranchesItem.getNode("abc").select(); |
| ContextMenuHelper.clickContextMenuSync(tree, |
| myUtil.getPluginLocalizedValue("RepoViewDeleteBranch.label")); |
| |
| refreshAndWait(); |
| SWTBotTreeItem[] items = myRepoViewUtil |
| .getLocalBranchesItem(tree, repositoryFile).getItems(); |
| assertEquals("Wrong number of branches", 2, items.length); |
| assertEquals("master", items[0].getText()); |
| assertEquals("stable", items[1].getText()); |
| } |
| |
| @Test |
| public void testDeleteBranchMultiple() throws Exception { |
| // expand first level |
| SWTBotTree tree = getOrOpenView().bot().tree(); |
| refreshAndWait(); |
| // open a branch (checkout) |
| SWTBotTreeItem localBranchesItem = TestUtil.expandAndWait( |
| myRepoViewUtil.getLocalBranchesItem(tree, repositoryFile)); |
| SWTBotTreeItem masterNode = localBranchesItem.getNode("master"); |
| // create first branch (abc) |
| masterNode.select(); |
| ContextMenuHelper.clickContextMenu(tree, "Create Branch..."); |
| SWTBotShell createBranchShell = bot |
| .shell(UIText.CreateBranchWizard_NewBranchTitle); |
| createBranchShell.bot().textWithId("BranchName").setText("abc"); |
| createBranchShell.bot().checkBox(UIText.CreateBranchPage_CheckoutButton) |
| .deselect(); |
| createBranchShell.bot().button(IDialogConstants.FINISH_LABEL).click(); |
| bot.waitUntil(shellCloses(createBranchShell), 10000); |
| refreshAndWait(); |
| // create second branch (123) |
| ContextMenuHelper.clickContextMenu(tree, "Create Branch..."); |
| createBranchShell = bot.shell(UIText.CreateBranchWizard_NewBranchTitle); |
| SWTBotText bn = createBranchShell.bot().textWithId("BranchName"); |
| bn.setText("123"); |
| createBranchShell.bot().checkBox(UIText.CreateBranchPage_CheckoutButton) |
| .deselect(); |
| createBranchShell.bot().button(IDialogConstants.FINISH_LABEL).click(); |
| bot.waitUntil(shellCloses(createBranchShell), 10000); |
| refreshAndWait(); |
| localBranchesItem = TestUtil.expandAndWait( |
| myRepoViewUtil.getLocalBranchesItem(tree, repositoryFile)); |
| // delete both |
| localBranchesItem.select("abc", "123"); |
| ContextMenuHelper.clickContextMenuSync(tree, |
| myUtil.getPluginLocalizedValue("RepoViewDeleteBranch.label")); |
| refreshAndWait(); |
| |
| SWTBotTreeItem[] items = myRepoViewUtil |
| .getLocalBranchesItem(tree, repositoryFile).getItems(); |
| assertEquals("Wrong number of branches", 2, items.length); |
| assertEquals("master", items[0].getText()); |
| assertEquals("stable", items[1].getText()); |
| } |
| |
| @Test |
| public void testDeleteFileInProject() throws Exception { |
| SWTBotTree tree = getOrOpenView().bot().tree(); |
| refreshAndWait(); |
| |
| IProject project1 = ResourcesPlugin.getWorkspace().getRoot() |
| .getProject(PROJ1); |
| // Make sure that the refresh doesn't happen on delete and cause a |
| // timeout |
| project1.refreshLocal(IResource.DEPTH_INFINITE, null); |
| |
| SWTBotTreeItem folder = findWorkdirNode(tree, PROJ1, FOLDER); |
| folder.getNode(FILE1).select(); |
| |
| ContextMenuHelper.clickContextMenu(tree, |
| myUtil.getPluginLocalizedValue("RepoViewDeleteFile.label")); |
| |
| SWTBotShell confirm = bot.shell("Delete Resources"); |
| confirm.bot().button(IDialogConstants.OK_LABEL).click(); |
| bot.waitUntil(shellCloses(confirm)); |
| TestUtil.joinJobs(JobFamilies.REPO_VIEW_REFRESH); |
| |
| folder = findWorkdirNode(tree, PROJ1, FOLDER); |
| assertThat(folder.getNodes(), not(hasItem(FILE1))); |
| assertThat(folder.getNodes(), hasItem(FILE2)); |
| } |
| |
| @Test |
| public void testDeleteFileNotInProject() throws Exception { |
| // PROJ2 is still a valid Eclipse project at that point, even though the |
| // .project file wasn't committed. Close it. |
| ResourcesPlugin.getWorkspace().getRoot().getProject(PROJ2).close(null); |
| SWTBotTree tree = getOrOpenView().bot().tree(); |
| refreshAndWait(); |
| |
| SWTBotTreeItem folder = findWorkdirNode(tree, PROJ2, FOLDER); |
| int n = folder.getNodes().size(); |
| folder.getNode(FILE1).select(); |
| |
| ContextMenuHelper.clickContextMenu(tree, |
| myUtil.getPluginLocalizedValue("RepoViewDeleteFile.label")); |
| |
| SWTBotShell confirm = bot |
| .shell(UIText.DeletePathsOperationUI_confirmActionTitle); |
| confirm.bot().button(UIText.DeletePathsOperationUI_ButtonOK).click(); |
| bot.waitUntil(shellCloses(confirm)); |
| bot.waitUntil(new DefaultCondition() { |
| |
| @Override |
| public boolean test() throws Exception { |
| SWTBotTreeItem item = findWorkdirNode(tree, PROJ2, FOLDER); |
| return item.getNodes().size() == n - 1; |
| } |
| |
| @Override |
| public String getFailureMessage() { |
| return "File deletion not reflected in repo view tree within timout"; |
| } |
| }, 20000); |
| folder = findWorkdirNode(tree, PROJ2, FOLDER); |
| assertThat(folder.getNodes(), not(hasItem(FILE1))); |
| assertThat(folder.getNodes(), hasItem(FILE2)); |
| } |
| |
| @Test |
| public void testStashDeleteCreate() throws Exception { |
| Repository repo = lookupRepository(repositoryFile); |
| IFile file = touch("Something"); |
| new StashCreateOperation(repo, "First stash").execute(null); |
| file.refreshLocal(IResource.DEPTH_ZERO, null); |
| touch("Something else"); |
| new StashCreateOperation(repo, "Second stash").execute(null); |
| file.refreshLocal(IResource.DEPTH_ZERO, null); |
| touch("Something else again"); |
| new StashCreateOperation(repo, "Third stash").execute(null); |
| file.refreshLocal(IResource.DEPTH_ZERO, null); |
| SWTBotTree tree = getOrOpenView().bot().tree(); |
| refreshAndWait(); |
| |
| SWTBotTreeItem item = myRepoViewUtil.getStashesItem(tree, |
| repositoryFile); |
| item = TestUtil.expandAndWait(item); |
| assertEquals("Unexpected number of stashed commits", 3, |
| item.getItems().length); |
| item.getNode(0).select(); |
| ContextMenuHelper.clickContextMenu(tree, |
| myUtil.getPluginLocalizedValue("StashDropCommand.label")); |
| SWTBotShell confirm = bot.shell(UIText.StashDropCommand_confirmTitle); |
| confirm.bot().button(UIText.StashDropCommand_buttonDelete).click(); |
| bot.waitUntil(shellCloses(confirm)); |
| TestUtil.joinJobs(JobFamilies.STASH); |
| TestUtil.joinJobs(JobFamilies.REPO_VIEW_REFRESH); |
| touch("Something different"); |
| tree.getAllItems()[0].select(); |
| ContextMenuHelper.clickContextMenu(tree, |
| myUtil.getPluginLocalizedValue("StashesMenu.label"), |
| UIText.StashesMenu_StashChangesActionText); |
| confirm = bot.shell(UIText.StashCreateCommand_titleEnterCommitMessage); |
| confirm.bot().button(UIText.StashCreateCommand_ButtonOK).click(); |
| bot.waitUntil(shellCloses(confirm)); |
| TestUtil.joinJobs(JobFamilies.STASH); |
| TestUtil.joinJobs(JobFamilies.REPO_VIEW_REFRESH); |
| item = myRepoViewUtil.getStashesItem(tree, repositoryFile); |
| assertStashes(item.getItems(), 3); |
| } |
| |
| @Test |
| public void testStashDeleteMultiple() throws Exception { |
| Repository repo = lookupRepository(repositoryFile); |
| IFile file = touch("Something"); |
| new StashCreateOperation(repo, "First stash").execute(null); |
| file.refreshLocal(IResource.DEPTH_ZERO, null); |
| touch("Something else"); |
| new StashCreateOperation(repo, "Second stash").execute(null); |
| file.refreshLocal(IResource.DEPTH_ZERO, null); |
| touch("Something else again"); |
| new StashCreateOperation(repo, "Third stash").execute(null); |
| file.refreshLocal(IResource.DEPTH_ZERO, null); |
| SWTBotTree tree = getOrOpenView().bot().tree(); |
| refreshAndWait(); |
| |
| SWTBotTreeItem item = myRepoViewUtil.getStashesItem(tree, |
| repositoryFile); |
| item = TestUtil.expandAndWait(item); |
| assertEquals("Unexpected number of stashed commits", 3, |
| item.getItems().length); |
| item.select(1, 2); |
| ContextMenuHelper.clickContextMenu(tree, |
| myUtil.getPluginLocalizedValue("StashDropCommand.label")); |
| SWTBotShell confirm = bot.shell(UIText.StashDropCommand_confirmTitle); |
| confirm.bot().button(UIText.StashDropCommand_buttonDelete).click(); |
| bot.waitUntil(shellCloses(confirm)); |
| TestUtil.joinJobs(JobFamilies.STASH); |
| TestUtil.joinJobs(JobFamilies.REPO_VIEW_REFRESH); |
| item = myRepoViewUtil.getStashesItem(tree, repositoryFile); |
| assertStashes(item.getItems(), 1, "Third stash"); |
| } |
| |
| private void assertStashes(SWTBotTreeItem[] children, int expectedSize, |
| String... decorations) |
| throws Exception { |
| assertEquals("Expected " + expectedSize + " children", expectedSize, |
| children.length); |
| if (decorations != null && decorations.length > 0) { |
| TestUtil.waitForDecorations(); |
| } |
| int[] indices = new int[expectedSize]; |
| int[] expectedIndices = new int[expectedSize]; |
| for (int i = 0; i < indices.length; i++) { |
| indices[i] = -1; |
| expectedIndices[i] = i; |
| } |
| children[0].display.syncExec(() -> { |
| int j = 0; |
| for (SWTBotTreeItem child : children) { |
| Object data = child.widget.getData(); |
| if (data instanceof StashedCommitNode) { |
| indices[j++] = ((StashedCommitNode) data).getIndex(); |
| } |
| } |
| }); |
| assertArrayEquals("Unexpected stash indices", expectedIndices, indices); |
| for (int i = 0; i < children.length; i++) { |
| String text = children[i].getText(); |
| assertTrue("Stash " + i + " has wrong label: " + text, |
| text.startsWith("stash@{" + i + "}")); |
| if (decorations != null && i < decorations.length) { |
| String deco = decorations[i]; |
| if (deco != null) { |
| assertTrue("Label should contain '" + deco + "': " + text, |
| text.contains(deco)); |
| } |
| } |
| } |
| } |
| |
| private void toggleLinkWithSelection() throws Exception { |
| getOrOpenView().toolbarButton( |
| myUtil.getPluginLocalizedValue( |
| "RepoViewLinkWithSelection.tooltip")) |
| .click(); |
| } |
| |
| private SWTBotTreeItem findWorkdirNode(SWTBotTree tree, String... nodes) |
| throws Exception { |
| SWTBotTreeItem item = myRepoViewUtil.getWorkdirItem(tree, |
| repositoryFile); |
| for (String node : nodes) { |
| item = TestUtil.expandAndWait(item).getNode(node); |
| } |
| return item.expand(); |
| } |
| } |