refactor: simplify collection.toArray()
[egit/eclipse.git] / org.eclipse.egit.ui.test / src / org / eclipse / egit / ui / view / synchronize / SynchronizeViewGitChangeSetModelTest.java
blobcb5fe6f1411e550b29f0ba57c299145e3154d238
1 /*******************************************************************************
2 * Copyright (C) 2010-2013 Dariusz Luksza <dariusz@luksza.org> and others.
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
9 * SPDX-License-Identifier: EPL-2.0
10 *******************************************************************************/
11 package org.eclipse.egit.ui.view.synchronize;
13 import static org.eclipse.egit.ui.internal.UIText.GitModelWorkingTree_workingTree;
14 import static org.eclipse.jgit.lib.Constants.HEAD;
15 import static org.eclipse.jgit.lib.Constants.MASTER;
16 import static org.eclipse.jgit.lib.Constants.R_HEADS;
17 import static org.eclipse.jgit.lib.Constants.R_TAGS;
18 import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.allOf;
19 import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.widgetOfType;
20 import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.withRegex;
21 import static org.hamcrest.CoreMatchers.equalTo;
22 import static org.hamcrest.CoreMatchers.is;
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertNotNull;
25 import static org.junit.Assert.assertNotSame;
26 import static org.junit.Assert.assertThat;
27 import static org.junit.Assert.assertTrue;
29 import java.io.BufferedWriter;
30 import java.io.ByteArrayInputStream;
31 import java.io.File;
32 import java.io.FileOutputStream;
33 import java.io.OutputStreamWriter;
35 import org.eclipse.core.resources.IFile;
36 import org.eclipse.core.resources.IProject;
37 import org.eclipse.core.resources.IResource;
38 import org.eclipse.core.resources.ResourcesPlugin;
39 import org.eclipse.core.runtime.jobs.Job;
40 import org.eclipse.egit.ui.common.CompareEditorTester;
41 import org.eclipse.egit.ui.internal.CommonUtils;
42 import org.eclipse.egit.ui.internal.UIText;
43 import org.eclipse.egit.ui.internal.repository.RepositoriesView;
44 import org.eclipse.egit.ui.internal.synchronize.GitChangeSetModelProvider;
45 import org.eclipse.egit.ui.test.TestUtil;
46 import org.eclipse.jgit.api.Git;
47 import org.eclipse.jgit.api.Status;
48 import org.eclipse.jgit.lib.Repository;
49 import org.eclipse.swt.widgets.Display;
50 import org.eclipse.swt.widgets.Label;
51 import org.eclipse.swtbot.swt.finder.SWTBot;
52 import org.eclipse.swtbot.swt.finder.widgets.SWTBotLabel;
53 import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree;
54 import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
55 import org.eclipse.team.ui.synchronize.ISynchronizeView;
56 import org.hamcrest.Matcher;
57 import org.junit.Before;
58 import org.junit.Ignore;
59 import org.junit.Test;
61 public class SynchronizeViewGitChangeSetModelTest extends
62 AbstractSynchronizeViewTest {
64 @Before
65 public void setUpEnabledModelProvider() {
66 setEnabledModelProvider(GitChangeSetModelProvider.ID);
69 @Test
70 public void shouldReturnNoChanges() throws Exception {
71 // given
72 changeFilesInProject();
74 // when
75 launchSynchronization(HEAD, R_HEADS + MASTER, false);
77 // then
78 SWTBot viewBot = bot.viewById(ISynchronizeView.VIEW_ID).bot();
79 @SuppressWarnings("unchecked")
80 Matcher matcher = allOf(widgetOfType(Label.class),
81 withRegex("No changes in .*"));
83 @SuppressWarnings("unchecked")
84 SWTBotLabel l = new SWTBotLabel((Label) viewBot.widget(matcher));
85 assertNotNull(l);
88 @Test
89 public void shouldReturnListOfChanges() throws Exception {
90 // given
91 changeFilesInProject();
93 // when
94 launchSynchronization(HEAD, HEAD, true);
96 // then
97 SWTBotTreeItem workingTreeItem = getExpandedWorkingTreeItem();
98 assertTrue(workingTreeItem.getText().endsWith(GitModelWorkingTree_workingTree));
101 @Test
102 public void shouldCompareBranchAgainstTag() throws Exception {
103 // given
104 makeChangesAndCommit(PROJ1);
106 // when
107 launchSynchronization(INITIAL_TAG, HEAD, false);
109 // then
110 SWTBotTreeItem changeSetTreeItem = getChangeSetTreeItem();
111 assertEquals(1, changeSetTreeItem.getItems().length);
114 @Test
115 public void shouldCompareTagAgainstTag() throws Exception {
116 // given
117 makeChangesAndCommit(PROJ1);
118 createTag("v0.1");
120 // when
121 launchSynchronization(INITIAL_TAG, R_TAGS + "v0.1", false);
123 // then
124 SWTBotTreeItem changeSetTreeItem = getChangeSetTreeItem();
125 assertEquals(1, changeSetTreeItem.getItems().length);
128 @Test
129 public void shouldOpenCompareEditor() throws Exception {
130 // given
131 changeFilesInProject();
133 // when
134 launchSynchronization(HEAD, INITIAL_TAG, true);
136 // then
137 CompareEditorTester compare = getCompareEditorForFileInGitChangeSet(
138 FILE1, true);
139 assertNotNull(compare);
142 @Test
143 public void shouldListFileDeletedChange() throws Exception {
144 // given
145 deleteFileAndCommit(PROJ1);
147 // when
148 launchSynchronization(HEAD, HEAD + "~1", true);
150 // then
151 SWTBotTreeItem changeSetTreeItem = getChangeSetTreeItem();
152 assertEquals(1, changeSetTreeItem.getItems().length);
154 SWTBotTreeItem commitTree = waitForNodeWithText(changeSetTreeItem,
155 TEST_COMMIT_MSG);
156 SWTBotTreeItem projectTree = waitForNodeWithText(commitTree, PROJ1);
157 assertEquals(1, projectTree.getItems().length);
159 SWTBotTreeItem folderTree = waitForNodeWithText(projectTree, FOLDER);
160 assertEquals(1, folderTree.getItems().length);
162 SWTBotTreeItem fileTree = folderTree.getItems()[0];
163 assertEquals("test.txt", fileTree.getText());
166 @Test
167 public void shouldSynchronizeInEmptyRepository() throws Exception {
168 // given
169 createEmptyRepository();
171 // when
172 launchSynchronization(EMPTY_PROJECT, "", "", true);
174 // then
175 SWTBotTreeItem workingTree = getExpandedWorkingTreeItem();
176 SWTBotTreeItem projectTree = waitForNodeWithText(workingTree,
177 EMPTY_PROJECT);
178 assertEquals(2, projectTree.getItems().length);
180 SWTBotTreeItem folderTree = waitForNodeWithText(projectTree, FOLDER);
181 assertEquals(2, folderTree.getItems().length);
183 SWTBotTreeItem fileTree = folderTree.getItems()[0];
184 assertEquals(FILE1, fileTree.getText());
185 fileTree = folderTree.getItems()[1];
186 assertEquals(FILE2, fileTree.getText());
189 @Test
190 public void shouldExchangeCompareEditorSidesBetweenIncomingAndOutgoingChanges()
191 throws Exception {
192 // given
193 makeChangesAndCommit(PROJ1);
195 // compare HEAD against tag
196 launchSynchronization(HEAD, INITIAL_TAG, false);
198 CompareEditorTester outgoingCompare = getCompareEditorForFileInGitChangeSet(
199 FILE1, false);
200 // save left value from compare editor
201 String outgoingLeft = outgoingCompare.getLeftEditor().getText();
202 // save right value from compare editor
203 String outgoingRight = outgoingCompare.getRightEditor().getText();
204 outgoingCompare.close();
206 assertNotSame("Text from SWTBot widgets was the same", outgoingLeft, outgoingRight);
208 // when
209 // compare tag against HEAD
210 launchSynchronization(INITIAL_TAG, HEAD, false);
212 // then
213 CompareEditorTester incomingComp = getCompareEditorForFileInGitChangeSet(
214 FILE1, false);
215 // right side from compare editor should be equal with left
216 assertThat(outgoingLeft, equalTo(incomingComp.getRightEditor().getText()));
217 // left side from compare editor should be equal with right
218 assertThat(outgoingRight, equalTo(incomingComp.getLeftEditor().getText()));
221 @Test
222 public void shouldNotShowIgnoredFiles()
223 throws Exception {
224 // given
225 String ignoredName = "to-be-ignored.txt";
227 IProject proj = ResourcesPlugin.getWorkspace().getRoot()
228 .getProject(PROJ1);
230 IFile ignoredFile = proj.getFile(ignoredName);
231 ignoredFile.create(new ByteArrayInputStream("content of ignored file"
232 .getBytes(proj.getDefaultCharset())), false, null);
234 IFile gitignore = proj.getFile(".gitignore");
235 gitignore.create(
236 new ByteArrayInputStream(ignoredName.getBytes(proj
237 .getDefaultCharset())), false, null);
238 proj.refreshLocal(IResource.DEPTH_INFINITE, null);
240 // when
241 launchSynchronization(INITIAL_TAG, HEAD, true);
243 // then
244 // asserts for Git Change Set model
245 SWTBotTreeItem workingTree = getExpandedWorkingTreeItem();
246 assertEquals(1, workingTree.getItems().length);
247 SWTBotTreeItem proj1Node = workingTree.getItems()[0];
248 assertEquals(1, proj1Node.getItems().length);
249 assertEquals(".gitignore", proj1Node.getItems()[0].getText());
252 @Test
253 public void shouldShowNonWorkspaceFileInSynchronization()
254 throws Exception {
255 // given
256 String name = "non-workspace.txt";
257 File root = new File(getTestDirectory(), REPO1);
258 File nonWorkspace = new File(root, name);
259 BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
260 new FileOutputStream(nonWorkspace), "UTF-8"));
262 writer.append("file content");
263 writer.close();
264 // TODO Synchronize currently shows "No changes" when the only thing that has
265 // changed is a non-workspace file, so add another change so that this
266 // does not happen. When the bug is fixed, this should be removed.
267 setTestFileContent("other content");
269 // when
270 launchSynchronization(INITIAL_TAG, HEAD, true);
272 // then
273 SWTBotTreeItem workingTree = getExpandedWorkingTreeItem();
274 assertEquals(1, workingTree.getNodes(name).size());
277 @Test
278 public void shouldShowCompareEditorForNonWorkspaceFileFromSynchronization()
279 throws Exception {
280 // given
281 String content = "file content";
282 String name = "non-workspace.txt";
283 File root = new File(getTestDirectory(), REPO1);
284 File nonWorkspace = new File(root, name);
285 BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
286 new FileOutputStream(nonWorkspace), "UTF-8"));
287 writer.append(content);
288 writer.close();
289 // TODO Synchronize currently shows "No changes" when the only thing that has
290 // changed is a non-workspace file, so add another change so that this
291 // does not happen. When the bug is fixed, this should be removed.
292 setTestFileContent("other content");
294 // when
295 launchSynchronization(INITIAL_TAG, HEAD, true);
297 // then
298 CompareEditorTester editor = getCompareEditorForNonWorkspaceFileInGitChangeSet(name);
300 String left = editor.getLeftEditor().getText();
301 String right = editor.getRightEditor().getText();
302 assertEquals(content, left);
303 assertEquals("", right);
306 @Test
307 public void shouldStagePartialChangeInCompareEditor() throws Exception {
308 // given
309 changeFilesInProject();
310 launchSynchronization(HEAD, HEAD, true);
311 CompareEditorTester compareEditor = getCompareEditorForFileInGitChangeSet(
312 FILE1, true);
314 // when
315 Display.getDefault().syncExec(new Runnable() {
316 @Override
317 public void run() {
318 CommonUtils.runCommand("org.eclipse.compare.copyLeftToRight",
319 null);
322 compareEditor.save();
325 // then file FILE1 should be in index
326 Repository repo = lookupRepository(repositoryFile);
327 Status status;
328 try (Git git = new Git(repo)) {
329 status = git.status().call();
331 assertThat(Long.valueOf(status.getChanged().size()),
332 is(Long.valueOf(1L)));
333 assertThat(status.getChanged().iterator().next(),
334 is(PROJ1 + "/" + FOLDER + "/" + FILE1));
337 @Test
338 public void shouldUnStagePartialChangeInCompareEditor() throws Exception {
339 // given
340 changeFilesInProject();
341 launchSynchronization(HEAD, HEAD, true);
342 CompareEditorTester compareEditor = getCompareEditorForFileInGitChangeSet(
343 FILE1, true);
345 // when
346 Display.getDefault().syncExec(new Runnable() {
347 @Override
348 public void run() {
349 CommonUtils.runCommand("org.eclipse.compare.copyRightToLeft",
350 null);
353 compareEditor.save();
355 // then file FILE1 should be unchanged in working tree
356 Repository repo = lookupRepository(repositoryFile);
357 try (Git git = new Git(repo)) {
358 Status status = git.status().call();
359 assertThat(Long.valueOf(status.getModified().size()),
360 is(Long.valueOf(1)));
361 assertThat(status.getModified().iterator().next(),
362 is(PROJ1 + "/" + FOLDER + "/" + FILE2));
366 @Test
367 public void shouldRefreshSyncResultAfterWorkspaceChange() throws Exception {
368 // given
369 String newFileName = "new.txt";
370 launchSynchronization(INITIAL_TAG, HEAD, true);
371 IProject proj = ResourcesPlugin.getWorkspace().getRoot()
372 .getProject(PROJ1);
374 // when
375 IFile newFile = proj.getFile(newFileName);
376 newFile.create(
377 new ByteArrayInputStream("content of new file".getBytes(proj
378 .getDefaultCharset())), false, null);
379 // force refresh
380 proj.refreshLocal(IResource.DEPTH_INFINITE, null);
381 Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_BUILD, null);
383 // then
384 SWTBotTreeItem workingTree = getExpandedWorkingTreeItem();
385 assertTrue(workingTree.getText()
386 .endsWith(GitModelWorkingTree_workingTree));
387 // WidgetNotFoundException will be thrown when node named 'new.txt' not
388 // exists
389 assertNotNull(TestUtil.getNode(workingTree.getItems(), PROJ1)
390 .getNode(newFileName));
393 @Test
394 public void shouldRefreshSyncResultAfterRepositoryChange() throws Exception {
395 // given
396 changeFilesInProject();
397 launchSynchronization(HEAD, HEAD, true);
399 // preconditions - sync result should contain two uncommitted changes
400 SWTBotTreeItem workingTree = getExpandedWorkingTreeItem();
401 assertTrue(workingTree.getText().endsWith(GitModelWorkingTree_workingTree));
402 assertEquals(2,
403 workingTree.getItems()[0].getItems()[0].getItems().length);
405 // when
406 commit(PROJ1);
408 // then - synchronize view should be empty
409 SWTBot viewBot = bot.viewById(ISynchronizeView.VIEW_ID).bot();
410 @SuppressWarnings("unchecked")
411 Matcher matcher = allOf(widgetOfType(Label.class),
412 withRegex("No changes in .*"));
414 @SuppressWarnings("unchecked")
415 SWTBotLabel l = new SWTBotLabel((Label) viewBot.widget(matcher));
416 assertNotNull(l);
419 // this test always fails with cause:
420 // Timeout after: 5000 ms.: Could not find context menu with text:
421 // Synchronize
422 @Ignore
423 @Test
424 public void shouldLaunchSynchronizationFromGitRepositories()
425 throws Exception {
426 // given
427 bot.menu("Window").menu("Show View").menu("Other...").click();
428 bot.shell("Show View").bot().tree().expandNode("Git").getNode(
429 "Git Repositories").doubleClick();
431 SWTBotTree repositoriesTree = bot.viewById(RepositoriesView.VIEW_ID)
432 .bot()
433 .tree();
434 SWTBotTreeItem egitRoot = repositoriesTree.getAllItems()[0];
435 egitRoot.expand();
436 egitRoot.collapse();
437 egitRoot.expand();
438 SWTBotTreeItem remoteBranch = egitRoot.expandNode("Branches")
439 .expandNode("Remote Branches");
440 SWTBotTreeItem branchNode = remoteBranch.getNode("origin/stable-0.7");
441 branchNode.select();
442 branchNode.contextMenu("Synchronize").click();
444 // when
446 // then
447 SWTBotTree syncViewTree = bot.viewById(ISynchronizeView.VIEW_ID).bot().tree();
448 assertEquals(8, syncViewTree.getAllItems().length);
451 protected SWTBotTreeItem getChangeSetTreeItem() {
452 SWTBotTree syncViewTree = bot.viewById(ISynchronizeView.VIEW_ID).bot().tree();
453 SWTBotTreeItem changeSetItem = waitForNodeWithText(syncViewTree,
454 UIText.GitChangeSetModelProviderLabel);
455 return changeSetItem;
458 protected CompareEditorTester getCompareEditorForFileInGitChangeSet(
459 String fileName,
460 boolean includeLocalChanges) {
461 SWTBotTreeItem changeSetTreeItem = getChangeSetTreeItem();
463 SWTBotTreeItem rootTree;
464 if (includeLocalChanges)
465 rootTree = waitForNodeWithText(changeSetTreeItem,
466 GitModelWorkingTree_workingTree);
467 else
468 rootTree = waitForNodeWithText(changeSetTreeItem, TEST_COMMIT_MSG);
470 SWTBotTreeItem projNode = waitForNodeWithText(rootTree, PROJ1);
471 return getCompareEditor(projNode, fileName);
474 protected CompareEditorTester getCompareEditorForNonWorkspaceFileInGitChangeSet(
475 final String fileName) {
476 SWTBotTreeItem changeSetTreeItem = getChangeSetTreeItem();
478 SWTBotTreeItem rootTree = waitForNodeWithText(changeSetTreeItem,
479 GitModelWorkingTree_workingTree);
480 waitForNodeWithText(rootTree, fileName).doubleClick();
482 return CompareEditorTester.forTitleContaining(fileName);
485 private SWTBotTreeItem getExpandedWorkingTreeItem() {
486 SWTBotTreeItem changeSetTreeItem = getChangeSetTreeItem();
487 String workingTreeNodeNameString = getWorkingTreeNodeName(changeSetTreeItem);
488 SWTBotTreeItem node = changeSetTreeItem.getNode(workingTreeNodeNameString);
489 // Full expansion
490 return node.doubleClick();
493 private String getWorkingTreeNodeName(SWTBotTreeItem changeSetTreeItem) {
494 for (SWTBotTreeItem item : changeSetTreeItem.getItems()) {
495 String nodeName = item.getText();
496 if (nodeName.contains(UIText.GitModelWorkingTree_workingTree))
497 return nodeName;
500 return UIText.GitModelWorkingTree_workingTree;