blob: c3ccf1a4dafae746f10b5b9e587865aa193b405e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 Tasktop Technologies and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Tasktop Technologies - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.internal.tasks.ui.migrator;
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.Mockito.atLeastOnce;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.mylyn.internal.commons.notifications.feed.ServiceMessage;
import org.eclipse.mylyn.internal.tasks.ui.TaskListBackupManager;
import org.eclipse.mylyn.internal.tasks.ui.migrator.ConnectorMigrationUi.CompleteMigrationJob;
import org.eclipse.mylyn.internal.tasks.ui.notifications.TaskListServiceMessageControl;
import org.eclipse.mylyn.internal.tasks.ui.views.TaskListView;
import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector;
import org.eclipse.mylyn.tasks.core.IRepositoryManager;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.swt.widgets.Display;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
public class ConnectorMigrationUiTest {
private ConnectorMigrator migrator;
private final TaskListView taskList = mock(TaskListView.class);
private final TaskListBackupManager backupManager = mock(TaskListBackupManager.class);
private final ConnectorMigrationUi migrationUi = spy(
new ConnectorMigrationUi(taskList, backupManager, new DefaultTasksState()));
private CompleteMigrationJob completeMigrationJob;
@SuppressWarnings("unchecked")
@Before
public void setUp() {
doNothing().when(migrationUi).warnOfValidationFailure(any(List.class));
doNothing().when(migrationUi).notifyMigrationComplete();
}
@After
public void tearDown() {
if (completeMigrationJob != null) {
completeMigrationJob.dispose();
// otherwise it will keep rescheduling itself and interfere with other tests
}
}
@Test
public void promptToMigrate() {
ServiceMessage message = openMigrationPrompt(Window.OK);
assertEquals("End of Connector Support", message.getTitle());
assertTrue(message.getDescription().contains("<a href=\"migrate\">Click here</a>"));
assertEquals(Dialog.DLG_IMG_MESSAGE_INFO, message.getImage());
assertFalse(message.openLink("foo"));
verify(migrationUi, never()).createMigrationWizard(any(ConnectorMigrator.class));
verify(migrationUi, never()).createPromptToCompleteMigrationJob(any(ConnectorMigrator.class));
message.openLink("migrate");
}
@Test
public void finishMigrationWizard() throws Exception {
ServiceMessage message = openMigrationPrompt(Window.OK);
assertTrue(message.openLink("migrate"));
verify(migrationUi).createPromptToCompleteMigrationJob(any(ConnectorMigrator.class));
}
@Test
public void cancelMigrationWizard() throws Exception {
ServiceMessage message = openMigrationPrompt(Window.CANCEL);
assertFalse(message.openLink("migrate"));
verify(migrationUi, never()).createPromptToCompleteMigrationJob(any(ConnectorMigrator.class));
}
@Test
public void promptToMigrateOpensSecondMessage() {
ServiceMessage message = openMigrationPrompt(Window.OK);
Job job = mock(Job.class);
doReturn(job).when(migrationUi).createPromptToCompleteMigrationJob(any(ConnectorMigrator.class));
message.openLink("migrate");
verify(migrationUi).createMigrationWizard(any(ConnectorMigrator.class));
verify(migrationUi).createPromptToCompleteMigrationJob(any(ConnectorMigrator.class));
verify(job).schedule();
}
@Test
public void promptToCompleteMigration() throws InterruptedException {
ServiceMessage message = openCompleteMigrationPrompt(Window.OK);
assertEquals("Connector Migration", message.getTitle());
assertTrue(message.getDescription().contains("<a href=\"complete-migration\">complete migration</a>"));
assertEquals(Dialog.DLG_IMG_MESSAGE_WARNING, message.getImage());
assertFalse(message.openLink("foo"));
verify(migrationUi, never()).createCompleteMigrationWizard(any(ConnectorMigrator.class));
message.openLink("complete-migration");
verify(migrationUi).createCompleteMigrationWizard(any(ConnectorMigrator.class));
}
@Test
public void finishCompleteMigrationWizard() throws Exception {
ServiceMessage message = openCompleteMigrationPrompt(Window.OK);
assertTrue(message.openLink("complete-migration"));
}
@Test
public void cancelCompleteMigrationWizard() throws Exception {
ServiceMessage message = openCompleteMigrationPrompt(Window.CANCEL);
assertFalse(message.openLink("complete-migration"));
}
@Test
public void secondMessageReopensAfterDelay() throws Exception {
ServiceMessage message = openCompleteMigrationPrompt(Window.OK);
TaskListServiceMessageControl messageControl = createMessageControl();
Thread.sleep(2100);
ServiceMessage message2 = captureMessage(messageControl);
assertTrue(message2 != message);
Thread.sleep(2100);
ServiceMessage message3 = captureMessage(messageControl);
assertTrue(message3 != message2);
message3.openLink("complete-migration");
Thread.sleep(2100);
ServiceMessage message4 = captureMessage(messageControl);
assertTrue(message4 == message3);
}
@Test
public void backupTaskList() throws Exception {
ImmutableMap<String, String> kinds = ImmutableMap.of("mock", "mock.new");
TaskRepository repository = new TaskRepository("mock", "http://mock");
ConnectorMigrator migrator = spy(createMigrator(true, true, kinds, ImmutableSet.of(repository)));
IProgressMonitor monitor = mock(IProgressMonitor.class);
migrationUi.backupTaskList(monitor);
InOrder inOrder = inOrder(backupManager, migrationUi, migrator, monitor);
inOrder.verify(monitor).subTask("Backing up task list");
inOrder.verify(migrationUi).getBackupFileName(any(Date.class));
inOrder.verify(backupManager).backupNow(true);
inOrder.verify(monitor).worked(1);
}
@Test
public void getBackupFileName() throws Exception {
Date date = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.MILLISECOND, 0);
date = cal.getTime();
String fileName = migrationUi.getBackupFileName(date);
Matcher m = Pattern.compile("connector-migration-(\\d{4}_\\d{2}_\\d{2}_\\d{6}).zip").matcher(fileName);
Matcher dateFormatMatcher = Pattern.compile("\\d{4}-\\d{2}-\\d{2}-\\d{6}.zip").matcher(fileName);
Matcher oldDateFormatMatcher = Pattern.compile("\\d{4}-\\d{2}-\\d{2}").matcher(fileName);
assertTrue(m.matches());
assertFalse(dateFormatMatcher.find());
assertFalse(oldDateFormatMatcher.find());
Date fileNameTime = new SimpleDateFormat("yyyy_MM_dd_HHmmss").parse(m.group(1));
assertEquals(date, fileNameTime);
}
/**
* @param returnCode
* the return code of the wizard that opens when the link in the prompt is clicked
*/
private ServiceMessage openMigrationPrompt(int returnCode) {
TaskListServiceMessageControl messageControl = createMessageControl();
migrator = spy(
new ConnectorMigrator(ImmutableMap.of("mock", "mock.new"), "", new DefaultTasksState(), migrationUi));
WizardDialog wizard = mock(WizardDialog.class);
when(wizard.open()).thenReturn(returnCode);
doReturn(wizard).when(migrationUi).createMigrationWizard(any(ConnectorMigrator.class));
migrationUi.promptToMigrate(migrator);
return captureMessage(messageControl);
}
/**
* @param returnCode
* the return code of the wizard that opens when the link in the prompt is clicked
*/
private ServiceMessage openCompleteMigrationPrompt(int returnCode) throws InterruptedException {
TaskListServiceMessageControl messageControl = createMessageControl();
migrator = spy(
new ConnectorMigrator(ImmutableMap.of("mock", "mock.new"), "", new DefaultTasksState(), migrationUi));
when(migrationUi.getCompletionPromptFrequency()).thenReturn(2);
WizardDialog wizard = mock(WizardDialog.class);
when(wizard.open()).thenReturn(returnCode);
doReturn(wizard).when(migrationUi).createCompleteMigrationWizard(any(ConnectorMigrator.class));
completeMigrationJob = (CompleteMigrationJob) migrationUi.createPromptToCompleteMigrationJob(migrator);
assertTrue(completeMigrationJob.isSystem());
assertFalse(completeMigrationJob.isUser());
completeMigrationJob.schedule();
completeMigrationJob.join();
return captureMessage(messageControl);
}
private TaskListServiceMessageControl createMessageControl() {
TaskListServiceMessageControl messageControl = mock(TaskListServiceMessageControl.class);
when(taskList.getServiceMessageControl()).thenReturn(messageControl);
return messageControl;
}
private ServiceMessage captureMessage(TaskListServiceMessageControl messageControl) {
spinEventLoop();
ArgumentCaptor<ServiceMessage> messageCaptor = ArgumentCaptor.forClass(ServiceMessage.class);
verify(messageControl, atLeastOnce()).setMessage(messageCaptor.capture());
ServiceMessage message = messageCaptor.getValue();
return message;
}
private void spinEventLoop() {
while (Display.getCurrent().readAndDispatch()) {
}
}
private ConnectorMigrator createMigrator(boolean hasOldConnector, boolean hasNewConnector,
Map<String, String> kinds, Set<TaskRepository> repositories) {
IRepositoryManager manager = mock(IRepositoryManager.class);
AbstractRepositoryConnector connector = mock(AbstractRepositoryConnector.class);
ConnectorMigrator migrator = new ConnectorMigrator(kinds, "", new DefaultTasksState(), migrationUi);
when(manager.getRepositories("mock")).thenReturn(repositories);
if (hasOldConnector) {
when(manager.getRepositoryConnector("mock")).thenReturn(connector);
when(manager.getRepositoryConnector("kind")).thenReturn(connector);
}
if (hasNewConnector) {
when(manager.getRepositoryConnector("mock.new")).thenReturn(connector);
when(manager.getRepositoryConnector("kind.new")).thenReturn(connector);
}
return migrator;
}
}