package com.taskadapter.redmineapi; import com.taskadapter.redmineapi.bean.Changeset; import com.taskadapter.redmineapi.bean.CustomFieldDefinition; import com.taskadapter.redmineapi.bean.CustomFieldFactory; import com.taskadapter.redmineapi.bean.Issue; import com.taskadapter.redmineapi.bean.IssueCategory; import com.taskadapter.redmineapi.bean.IssueCategoryFactory; import com.taskadapter.redmineapi.bean.IssueFactory; import com.taskadapter.redmineapi.bean.IssueRelation; import com.taskadapter.redmineapi.bean.IssueStatus; import com.taskadapter.redmineapi.bean.Journal; import com.taskadapter.redmineapi.bean.JournalDetail; import com.taskadapter.redmineapi.bean.Project; import com.taskadapter.redmineapi.bean.SavedQuery; import com.taskadapter.redmineapi.bean.Tracker; import com.taskadapter.redmineapi.bean.User; import com.taskadapter.redmineapi.bean.Version; import com.taskadapter.redmineapi.bean.VersionFactory; import com.taskadapter.redmineapi.bean.Watcher; import com.taskadapter.redmineapi.bean.WatcherFactory; import com.taskadapter.redmineapi.internal.ResultsWrapper; import org.apache.http.client.HttpClient; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; import java.util.UUID; import static com.taskadapter.redmineapi.CustomFieldResolver.getCustomFieldByName; import static com.taskadapter.redmineapi.IssueHelper.createIssue; import static com.taskadapter.redmineapi.IssueHelper.createIssues; import com.taskadapter.redmineapi.bean.CustomField; import com.taskadapter.redmineapi.bean.Group; import com.taskadapter.redmineapi.bean.GroupFactory; import com.taskadapter.redmineapi.bean.Role; import com.taskadapter.redmineapi.bean.RoleFactory; import java.util.Arrays; import java.util.Collections; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; public class IssueManagerIT { private static IssueManager issueManager; private static ProjectManager projectManager; private static MembershipManager membershipManager; private static Project project; private static int projectId; private static String projectKey; private static Project project2; private static String projectKey2; private static RedmineManager mgr; private static UserManager userManager; private static Group demoGroup; @BeforeClass public static void oneTimeSetup() throws RedmineException { mgr = IntegrationTestHelper.createRedmineManager(); userManager = mgr.getUserManager(); issueManager = mgr.getIssueManager(); projectManager = mgr.getProjectManager(); membershipManager = mgr.getMembershipManager(); project = IntegrationTestHelper.createProject(mgr); projectId = project.getId(); projectKey = project.getIdentifier(); project2 = IntegrationTestHelper.createProject(mgr); projectKey2 = project2.getIdentifier(); Group g = GroupFactory.create(); g.setName("Group" + System.currentTimeMillis()); demoGroup = userManager.createGroup(g); // Add membership of group for the demo projects Collection<Role> allRoles = Arrays.asList(new Role[] { RoleFactory.create(3), // Manager RoleFactory.create(4), // Developer RoleFactory.create(5) // Reporter }); membershipManager.createMembershipForGroup(project.getId(), demoGroup.getId(), allRoles); membershipManager.createMembershipForGroup(project2.getId(), demoGroup.getId(), allRoles); } @AfterClass public static void oneTimeTearDown() throws RedmineException { IntegrationTestHelper.deleteProject(mgr, project.getIdentifier()); IntegrationTestHelper.deleteProject(mgr, project2.getIdentifier()); userManager.deleteGroup(demoGroup); } @Test public void issueCreated() throws RedmineException { Issue issueToCreate = IssueFactory.create(projectId, "test zzx"); Calendar startCal = Calendar.getInstance(); // have to clear them because they are ignored by Redmine and // prevent from comparison later startCal.clear(Calendar.HOUR_OF_DAY); startCal.clear(Calendar.MINUTE); startCal.clear(Calendar.SECOND); startCal.clear(Calendar.MILLISECOND); startCal.add(Calendar.DATE, 5); issueToCreate.setStartDate(startCal.getTime()); Calendar due = Calendar.getInstance(); due.add(Calendar.MONTH, 1); issueToCreate.setDueDate(due.getTime()); User ourUser = IntegrationTestHelper.getOurUser(); issueToCreate.setAssigneeId(ourUser.getId()); String description = "This is the description for the new task." + "\nIt has several lines." + "\nThis is the last line."; issueToCreate.setDescription(description); float estimatedHours = 44; issueToCreate.setEstimatedHours(estimatedHours); Issue newIssue = issueManager.createIssue(issueToCreate); assertNotNull("Checking returned result", newIssue); assertNotNull("New issue must have some ID", newIssue.getId()); // check startDate Calendar returnedStartCal = Calendar.getInstance(); returnedStartCal.setTime(newIssue.getStartDate()); assertEquals(startCal.get(Calendar.YEAR), returnedStartCal.get(Calendar.YEAR)); assertEquals(startCal.get(Calendar.MONTH), returnedStartCal.get(Calendar.MONTH)); assertEquals(startCal.get(Calendar.DAY_OF_MONTH), returnedStartCal.get(Calendar.DAY_OF_MONTH)); // check dueDate Calendar returnedDueCal = Calendar.getInstance(); returnedDueCal.setTime(newIssue.getDueDate()); assertEquals(due.get(Calendar.YEAR), returnedDueCal.get(Calendar.YEAR)); assertEquals(due.get(Calendar.MONTH), returnedDueCal.get(Calendar.MONTH)); assertEquals(due.get(Calendar.DAY_OF_MONTH), returnedDueCal.get(Calendar.DAY_OF_MONTH)); // check ASSIGNEE assertThat(ourUser.getId()).isEqualTo(newIssue.getAssigneeId()); // check AUTHOR Integer EXPECTED_AUTHOR_ID = IntegrationTestHelper.getOurUser().getId(); assertEquals(EXPECTED_AUTHOR_ID, newIssue.getAuthorId()); // check ESTIMATED TIME assertEquals((Float) estimatedHours, newIssue.getEstimatedHours()); // check multi-line DESCRIPTION String regexpStripExtra = "\\r|\\n|\\s"; description = description.replaceAll(regexpStripExtra, ""); String actualDescription = newIssue.getDescription(); actualDescription = actualDescription.replaceAll(regexpStripExtra, ""); assertEquals(description, actualDescription); // PRIORITY assertNotNull(newIssue.getPriorityId()); assertTrue(newIssue.getPriorityId() > 0); } @Test public void issueWithParentCreated() throws RedmineException { Issue parentIssue = IssueFactory.create(projectId, "parent 1"); Issue newParentIssue = issueManager.createIssue(parentIssue); assertNotNull("Checking parent was created", newParentIssue); assertNotNull("Checking ID of parent issue is not null", newParentIssue.getId()); // Integer parentId = 46; Integer parentId = newParentIssue.getId(); Issue childIssue = IssueFactory.create(projectId, "child 1"); childIssue.setParentId(parentId); Issue newChildIssue = issueManager.createIssue(childIssue); assertEquals("Checking parent ID of the child issue", parentId, newChildIssue.getParentId()); } /** * Regression test for https://github.com/taskadapter/redmine-java-api/issues/117 */ @Test public void parentIdCanBeErased() throws RedmineException { Issue parentIssue = IssueFactory.create(projectId, "parent task"); Issue newParentIssue = issueManager.createIssue(parentIssue); Integer parentId = newParentIssue.getId(); Issue childIssue = IssueFactory.create(projectId, "child task"); childIssue.setParentId(parentId); Issue newChildIssue = issueManager.createIssue(childIssue); assertThat(newChildIssue.getParentId()).isEqualTo(parentId); newChildIssue.setParentId(null); issueManager.update(newChildIssue); final Issue reloadedIssue = issueManager.getIssueById(newChildIssue.getId()); assertThat(reloadedIssue.getParentId()).isNull(); } @Test public void testUpdateIssue() throws RedmineException { String originalSubject = "Issue " + new Date(); Issue issue = IssueFactory.create(projectId, originalSubject); Issue newIssue = issueManager.createIssue(issue); String changedSubject = "changed subject"; newIssue.setSubject(changedSubject); issueManager.update(newIssue); Issue reloadedFromRedmineIssue = issueManager.getIssueById(newIssue.getId()); assertEquals("Checking if 'update issue' operation changed 'subject' field", changedSubject, reloadedFromRedmineIssue.getSubject()); } /** * Tests the retrieval of an {@link Issue} by its ID. * * @throws com.taskadapter.redmineapi.RedmineException * thrown in case something went wrong in Redmine * @throws RedmineAuthenticationException thrown in case something went wrong while trying to login * @throws com.taskadapter.redmineapi.NotFoundException * thrown in case the objects requested for could not be found */ @Test public void testGetIssueById() throws RedmineException { String originalSubject = "Issue " + new Date(); Issue issue = IssueFactory.create(projectId, originalSubject); Issue newIssue = issueManager.createIssue(issue); Issue reloadedFromRedmineIssue = issueManager.getIssueById(newIssue.getId()); assertEquals( "Checking if 'get issue by ID' operation returned issue with same 'subject' field", originalSubject, reloadedFromRedmineIssue.getSubject()); Tracker tracker = reloadedFromRedmineIssue.getTracker(); assertNotNull("Tracker of issue should not be null", tracker); assertNotNull("ID of tracker of issue should not be null", tracker.getId()); assertNotNull("Name of tracker of issue should not be null", tracker.getName()); } @Test public void testGetIssues() throws RedmineException { // create at least 1 issue Issue issueToCreate = IssueFactory.create(projectId, "testGetIssues: " + new Date()); Issue newIssue = issueManager.createIssue(issueToCreate); List<Issue> issues = issueManager.getIssues(projectKey, null); assertTrue(issues.size() > 0); boolean found = false; for (Issue issue : issues) { if (issue.getId().equals(newIssue.getId())) { found = true; break; } } if (!found) { fail("getIssues() didn't return the issue we just created. The query " + " must have returned all issues created during the last 2 days"); } } @Test(expected = NotFoundException.class) public void testGetIssuesInvalidQueryId() throws RedmineException { Integer invalidQueryId = 9999999; issueManager.getIssues(projectKey, invalidQueryId); } @Test public void testCreateIssueNonUnicodeSymbols() throws RedmineException { String nonLatinSymbols = "Example with accents A��o"; Issue toCreate = IssueFactory.create(projectId, nonLatinSymbols); Issue created = issueManager.createIssue(toCreate); assertEquals(nonLatinSymbols, created.getSubject()); } @Test public void testCreateIssueSummaryOnly() throws RedmineException { Issue issueToCreate = IssueFactory.create(projectId, "This is the summary line 123"); Issue newIssue = issueManager.createIssue(issueToCreate); assertNotNull("Checking returned result", newIssue); assertNotNull("New issue must have some ID", newIssue.getId()); // check AUTHOR Integer EXPECTED_AUTHOR_ID = IntegrationTestHelper.getOurUser().getId(); assertEquals(EXPECTED_AUTHOR_ID, newIssue.getAuthorId()); } @Test public void privateFlagIsRespectedWhenCreatingIssues() throws RedmineException { Issue privateIssueToCreate = IssueFactory.create(projectId, "private issue"); privateIssueToCreate.setPrivateIssue(true); Issue newIssue = issueManager.createIssue(privateIssueToCreate); assertThat(newIssue.isPrivateIssue()).isTrue(); Issue publicIssueToCreate = IssueFactory.create(projectId, "public issue"); publicIssueToCreate.setPrivateIssue(false); Issue newPublicIssue = issueManager.createIssue(publicIssueToCreate); assertThat(newPublicIssue.isPrivateIssue()).isFalse(); // default value for "is private" should be false Issue newDefaultIssue = issueManager.createIssue(IssueFactory.create(projectId, "default public issue")); assertThat(newDefaultIssue.isPrivateIssue()).isFalse(); } /* this test fails with Redmine 3.0.0-3.0.3 because Redmine 3.0.x started * returning "not authorized" instead of "not found" for projects with unknown Ids. * This worked differently with Redmine 2.6.x. * <p> * This test is not critical for the release of Redmine Java API library. I am marking it as "ignored" for now. */ @Ignore @Test(expected = NotFoundException.class) public void creatingIssueWithNonExistingProjectIdGivesNotFoundException() throws RedmineException { int nonExistingProjectId = 99999999; // hopefully this does not exist :) Issue issueToCreate = IssueFactory.create(nonExistingProjectId, "Summary line 100"); issueManager.createIssue(issueToCreate); } @Test(expected = NotFoundException.class) public void retrievingIssueWithNonExistingIdGivesNotFoundException() throws RedmineException { int someNonExistingID = 999999; issueManager.getIssueById(someNonExistingID); } @Test(expected = NotFoundException.class) public void updatingIssueWithNonExistingIdGivesNotFoundException() throws RedmineException { int nonExistingId = 999999; Issue issue = IssueFactory.create(nonExistingId); issueManager.update(issue); } @Test public void testGetIssuesPaging() throws RedmineException { // create 27 issues. default page size is 25. createIssues(issueManager, projectId, 27); List<Issue> issues = issueManager.getIssues(projectKey, null); assertThat(issues.size()).isGreaterThan(26); // check that there are no duplicates in the list. Set<Issue> issueSet = new HashSet<>(issues); assertThat(issueSet.size()).isEqualTo(issues.size()); } @Test public void canControlLimitAndOffsetDirectly() throws RedmineException { // create 27 issues. default Redmine page size is usually 25 (unless changed in the server settings). createIssues(issueManager, projectId, 27); Map<String, String> params = new HashMap<>(); params.put("limit", "3"); params.put("offset", "0"); params.put("project_id", projectId + ""); List<Issue> issues = issueManager.getIssues(params).getResults(); // only the requested number of issues is loaded, not all result pages. assertThat(issues.size()).isEqualTo(3); } @Test(expected = NotFoundException.class) public void testDeleteIssue() throws RedmineException { Issue issue = createIssues(issueManager, projectId, 1).get(0); Issue retrievedIssue = issueManager.getIssueById(issue.getId()); assertEquals(issue, retrievedIssue); issueManager.deleteIssue(issue.getId()); issueManager.getIssueById(issue.getId()); } @Test public void testUpdateIssueSpecialXMLtags() throws Exception { Issue issue = createIssues(issueManager, projectId, 1).get(0); String newSubject = "\"text in quotes\" and <xml> tags"; String newDescription = "<taghere>\"abc\"</here>"; issue.setSubject(newSubject); issue.setDescription(newDescription); issueManager.update(issue); Issue updatedIssue = issueManager.getIssueById(issue.getId()); assertEquals(newSubject, updatedIssue.getSubject()); assertEquals(newDescription, updatedIssue.getDescription()); } @Test public void testCreateRelation() throws RedmineException { List<Issue> issues = createIssues(issueManager, projectId, 2); Issue src = issues.get(0); Issue target = issues.get(1); String relationText = IssueRelation.TYPE.precedes.toString(); IssueRelation r = issueManager.createRelation(src.getId(), target.getId(), relationText); assertEquals(src.getId(), r.getIssueId()); assertEquals(target.getId(), r.getIssueToId()); assertEquals(relationText, r.getType()); } private IssueRelation createTwoRelatedIssues() throws RedmineException { List<Issue> issues = createIssues(issueManager, projectId, 2); Issue src = issues.get(0); Issue target = issues.get(1); String relationText = IssueRelation.TYPE.precedes.toString(); return issueManager.createRelation(src.getId(), target.getId(), relationText); } @Test public void issueRelationsAreCreatedAndLoadedOK() throws RedmineException { IssueRelation relation = createTwoRelatedIssues(); Issue issue = issueManager.getIssueById(relation.getIssueId(), Include.relations); Issue issueTarget = issueManager.getIssueById(relation.getIssueToId(), Include.relations); assertThat(issue.getRelations().size()).isEqualTo(1); assertThat(issueTarget.getRelations().size()).isEqualTo(1); IssueRelation relation1 = issue.getRelations().iterator().next(); assertThat(relation1.getIssueId()).isEqualTo(issue.getId()); assertThat(relation1.getIssueToId()).isEqualTo(issueTarget.getId()); assertThat(relation1.getType()).isEqualTo("precedes"); assertThat(relation1.getDelay()).isEqualTo((Integer) 0); IssueRelation reverseRelation = issueTarget.getRelations().iterator().next(); // both forward and reverse relations are the same! assertThat(reverseRelation).isEqualTo(relation1); } @Test public void issueRelationIsDeleted() throws RedmineException { IssueRelation relation = createTwoRelatedIssues(); issueManager.deleteRelation(relation.getId()); Issue issue = issueManager.getIssueById(relation.getIssueId(), Include.relations); assertThat(issue.getRelations()).isEmpty(); } @Test public void testIssueRelationsDelete() throws RedmineException { List<Issue> issues = createIssues(issueManager, projectId, 3); Issue src = issues.get(0); Issue target = issues.get(1); String relationText = IssueRelation.TYPE.precedes.toString(); issueManager.createRelation(src.getId(), target.getId(), relationText); target = issues.get(2); issueManager.createRelation(src.getId(), target.getId(), relationText); src = issueManager.getIssueById(src.getId(), Include.relations); issueManager.deleteIssueRelations(src); Issue issue = issueManager.getIssueById(src.getId(), Include.relations); assertTrue(issue.getRelations().isEmpty()); } /** * Requires Redmine 2.3 */ @Test public void testAddIssueWatcher() throws RedmineException { final Issue issue = createIssues(issueManager, projectId, 1).get(0); final Issue retrievedIssue = issueManager.getIssueById(issue.getId()); assertEquals(issue, retrievedIssue); final User newUser = userManager.createUser(UserGenerator.generateRandomUser()); try { Watcher watcher = WatcherFactory.create(newUser.getId()); issueManager.addWatcherToIssue(watcher, issue); } finally { userManager.deleteUser(newUser.getId()); } issueManager.getIssueById(issue.getId()); } /** * Requires Redmine 2.3 */ @Test public void testDeleteIssueWatcher() throws RedmineException { final Issue issue = createIssues(issueManager, projectId, 1).get(0); final Issue retrievedIssue = issueManager.getIssueById(issue.getId()); assertEquals(issue, retrievedIssue); final User newUser = userManager.createUser(UserGenerator.generateRandomUser()); try { Watcher watcher = WatcherFactory.create(newUser.getId()); issueManager.addWatcherToIssue(watcher, issue); issueManager.deleteWatcherFromIssue(watcher, issue); } finally { userManager.deleteUser(newUser.getId()); } issueManager.deleteIssue(issue.getId()); } /** * Requires Redmine 2.3 */ @Test public void testGetIssueWatcher() throws RedmineException { final Issue issue = createIssues(issueManager, projectId, 1).get(0); final Issue retrievedIssue = issueManager.getIssueById(issue.getId()); assertEquals(issue, retrievedIssue); final User newUser = userManager.createUser(UserGenerator.generateRandomUser()); try { Watcher watcher = WatcherFactory.create(newUser.getId()); issueManager.addWatcherToIssue(watcher, issue); final Issue includeWatcherIssue = issueManager.getIssueById(issue.getId(), Include.watchers); if (!includeWatcherIssue.getWatchers().isEmpty()) { Watcher watcher1 = includeWatcherIssue.getWatchers().iterator().next(); assertThat(watcher1.getId()).isEqualTo(newUser.getId()); } } finally { userManager.deleteUser(newUser.getId()); } issueManager.getIssueById(issue.getId()); } @Test public void testAddIssueWithWatchers() throws RedmineException { final Issue issue = IssueHelper.generateRandomIssue(projectId); final User newUserWatcher = userManager.createUser(UserGenerator.generateRandomUser()); try { List<Watcher> watchers = new ArrayList<>(); Watcher watcher = WatcherFactory.create(newUserWatcher.getId()); watchers.add(watcher); issue.addWatchers(watchers); final Issue retrievedIssue = issueManager.createIssue(issue); final Issue retrievedIssueWithWatchers = issueManager.getIssueById(retrievedIssue.getId(), Include.watchers); assertNotNull(retrievedIssueWithWatchers); assertNotNull(retrievedIssueWithWatchers.getWatchers()); assertEquals(watchers.size(), retrievedIssueWithWatchers.getWatchers().size()); assertEquals(watcher.getId(), retrievedIssueWithWatchers.getWatchers().iterator().next().getId()); } finally { userManager.deleteUser(newUserWatcher.getId()); } } @Test public void testGetIssuesBySummary() throws RedmineException { String summary = "issue with subject ABC"; Issue issue = IssueFactory.create(projectId, summary); User ourUser = IntegrationTestHelper.getOurUser(); issue.setAssigneeId(ourUser.getId()); Issue newIssue = issueManager.createIssue(issue); assertNotNull("Checking returned result", newIssue); assertNotNull("New issue must have some ID", newIssue.getId()); List<Issue> foundIssues = issueManager.getIssuesBySummary(projectKey, summary); assertNotNull("Checking if search results is not NULL", foundIssues); assertTrue("Search results must be not empty", !(foundIssues.isEmpty())); Issue loadedIssue1 = RedmineTestUtils.findIssueInList(foundIssues, newIssue.getId()); assertNotNull(loadedIssue1); assertEquals(summary, loadedIssue1.getSubject()); } @Test public void findByNonExistingSummaryReturnsEmptyList() throws RedmineException { String summary = "some summary here for issue which does not exist"; List<Issue> foundIssues = issueManager.getIssuesBySummary(projectKey, summary); assertNotNull("Search result must be not null", foundIssues); assertTrue("Search result list must be empty", foundIssues.isEmpty()); } @Test(expected = RedmineAuthenticationException.class) public void noAPIKeyOnCreateIssueThrowsAE() throws Exception { TestConfig testConfig = new TestConfig(); final HttpClient httpClient = IntegrationTestHelper.getHttpClientForTestServer(); RedmineManager redmineMgrEmpty = RedmineManagerFactory.createUnauthenticated(testConfig.getURI(), httpClient); Issue issue = IssueFactory.create(projectId, "test zzx"); redmineMgrEmpty.getIssueManager().createIssue(issue); } @Test(expected = RedmineAuthenticationException.class) public void wrongAPIKeyOnCreateIssueThrowsAE() throws Exception { TestConfig testConfig = new TestConfig(); final HttpClient httpClient = IntegrationTestHelper.getHttpClientForTestServer(); RedmineManager redmineMgrInvalidKey = RedmineManagerFactory.createWithApiKey( testConfig.getURI(), "wrong_key", httpClient); Issue issue = IssueFactory.create(projectId, "test zzx"); redmineMgrInvalidKey.getIssueManager().createIssue(issue); } @Test public void testIssueDoneRatio() throws RedmineException { Issue issue = IssueFactory.create(projectId, "Issue " + new Date()); Issue createdIssue = issueManager.createIssue(issue); assertEquals("Initial 'done ratio' must be 0", (Integer) 0, createdIssue.getDoneRatio()); Integer doneRatio = 50; createdIssue.setDoneRatio(doneRatio); issueManager.update(createdIssue); Integer issueId = createdIssue.getId(); Issue reloadedFromRedmineIssue = issueManager.getIssueById(issueId); assertEquals( "Checking if 'update issue' operation changed 'done ratio' field", doneRatio, reloadedFromRedmineIssue.getDoneRatio()); Integer invalidDoneRatio = 130; reloadedFromRedmineIssue.setDoneRatio(invalidDoneRatio); try { issueManager.update(reloadedFromRedmineIssue); } catch (RedmineProcessingException e) { assertEquals("Must be 1 error", 1, e.getErrors().size()); assertEquals("Checking error text", "% Done is not included in the list", e.getErrors() .get(0)); } Issue reloadedFromRedmineIssueUnchanged = issueManager.getIssueById(issueId); assertEquals( "'done ratio' must have remained unchanged after invalid value", doneRatio, reloadedFromRedmineIssueUnchanged.getDoneRatio()); } @Test public void nullDescriptionErasesItOnServer() throws RedmineException { Issue issue = new Issue(); String subject = "Issue " + new Date(); String descr = "Some description"; issue.setSubject(subject); issue.setDescription(descr); issue.setProjectId(projectId); Issue createdIssue = issueManager.createIssue(issue); assertThat(createdIssue.getDescription()).isEqualTo(descr); createdIssue.setDescription(null); issueManager.update(createdIssue); Integer issueId = createdIssue.getId(); Issue reloadedFromRedmineIssue = issueManager.getIssueById(issueId); assertThat(reloadedFromRedmineIssue.getDescription()).isNull(); } @Test public void testIssueJournals() throws RedmineException { // create at least 1 issue Issue issueToCreate = new Issue(); issueToCreate.setSubject("testGetIssues: " + new Date()); issueToCreate.setProjectId(projectId); Issue newIssue = issueManager.createIssue(issueToCreate); Issue loadedIssueWithJournals = issueManager.getIssueById(newIssue.getId(), Include.journals); assertTrue(loadedIssueWithJournals.getJournals().isEmpty()); String commentDescribingTheUpdate = "some comment describing the issue update"; loadedIssueWithJournals.setSubject("new subject"); loadedIssueWithJournals.setNotes(commentDescribingTheUpdate); issueManager.update(loadedIssueWithJournals); Issue loadedIssueWithJournals2 = issueManager.getIssueById(newIssue.getId(), Include.journals); assertEquals(1, loadedIssueWithJournals2.getJournals() .size()); Journal journalItem = loadedIssueWithJournals2.getJournals().iterator().next(); assertEquals(commentDescribingTheUpdate, journalItem.getNotes()); User ourUser = IntegrationTestHelper.getOurUser(); // can't compare User objects because either of them is not // completely filled assertEquals(ourUser.getId(), journalItem.getUser().getId()); assertEquals(ourUser.getFirstName(), journalItem.getUser() .getFirstName()); assertEquals(ourUser.getLastName(), journalItem.getUser() .getLastName()); assertEquals(1, journalItem.getDetails().size()); final JournalDetail journalDetail = journalItem.getDetails().get(0); assertEquals("new subject", journalDetail.getNewValue()); assertEquals("subject", journalDetail.getName()); assertEquals("attr", journalDetail.getProperty()); Issue loadedIssueWithoutJournals = issueManager.getIssueById(newIssue.getId()); assertTrue(loadedIssueWithoutJournals.getJournals().isEmpty()); } @Test public void updateIssueDescription() throws RedmineException { Issue issue = IssueFactory.create(projectId, "test123"); final Issue iss1 = issueManager.createIssue(issue); final Issue iss2 = IssueFactory.create(iss1.getId()); iss2.setProjectId(projectId); iss2.setDescription("This is a test"); issueManager.update(iss2); final Issue iss3 = issueManager.getIssueById(iss2.getId()); assertEquals("test123", iss3.getSubject()); assertEquals("This is a test", iss3.getDescription()); } @Test public void updateIssueTitle() throws RedmineException { Issue issue = IssueFactory.create(projectId, "test123"); issue.setDescription("Original description"); final Issue iss1 = issueManager.createIssue(issue); final Issue iss2 = IssueFactory.create(iss1.getId()); iss2.setSubject("New subject"); iss2.setProjectId(projectId); issueManager.update(iss2); final Issue iss3 = issueManager.getIssueById(iss2.getId()); assertEquals("New subject", iss3.getSubject()); assertEquals("Original description", iss3.getDescription()); } @Test public void testIssuePriorities() throws RedmineException { assertTrue(issueManager.getIssuePriorities().size() > 0); } @Test public void issueTargetVersionIsSetWhenCreatingOrUpdatingIssues() throws Exception { final String version1Name = "1.0"; final String version2Name = "2.0"; final Issue issueToCreate = IssueHelper.generateRandomIssue(projectId); Version version1 = createVersion(version1Name); issueToCreate.setTargetVersion(version1); issueToCreate.setProjectId(project.getId()); final Issue createdIssue = issueManager.createIssue(issueToCreate); assertNotNull(createdIssue.getTargetVersion()); assertEquals(createdIssue.getTargetVersion().getName(), version1Name); Version version2 = createVersion(version2Name); createdIssue.setTargetVersion(version2); issueManager.update(createdIssue); Issue updatedIssue = issueManager.getIssueById(createdIssue.getId()); assertThat(updatedIssue.getTargetVersion().getName()).isEqualTo(version2Name); createdIssue.setTargetVersion(null); issueManager.update(createdIssue); updatedIssue = issueManager.getIssueById(createdIssue.getId()); assertThat(updatedIssue.getTargetVersion()).isNull(); } private Version createVersion(String versionName) throws RedmineException { final Version version = VersionFactory.create(1); version.setName(versionName); version.setProjectId(projectId); return mgr.getProjectManager().createVersion(version); } @Test public void testUpdateIssueDoesNotChangeEstimatedTime() throws RedmineException { String originalSubject = "Issue " + new Date(); Issue issue = IssueFactory.create(projectId, originalSubject); Issue newIssue = issueManager.createIssue(issue); assertEquals("Estimated hours must be NULL", null, newIssue.getEstimatedHours()); issueManager.update(newIssue); Issue reloadedFromRedmineIssue = issueManager.getIssueById(newIssue.getId()); assertEquals("Estimated hours must be NULL", null, reloadedFromRedmineIssue.getEstimatedHours()); } /** * tests the retrieval of statuses. * * @throws RedmineProcessingException thrown in case something went wrong in Redmine * @throws java.io.IOException thrown in case something went wrong while performing I/O * operations * @throws RedmineAuthenticationException thrown in case something went wrong while trying to login * @throws NotFoundException thrown in case the objects requested for could not be found */ @Test public void testGetStatuses() throws RedmineException { // TODO we should create some statuses first, but the Redmine Java API // does not support this presently List<IssueStatus> statuses = issueManager.getStatuses(); assertFalse("Expected list of statuses not to be empty", statuses.isEmpty()); for (IssueStatus issueStatus : statuses) { // asserts on status assertNotNull("ID of status must not be null", issueStatus.getId()); assertNotNull("Name of status must not be null", issueStatus.getName()); } } /** * tests the creation and deletion of a {@link com.taskadapter.redmineapi.bean.IssueCategory}. * * @throws RedmineException thrown in case something went wrong in Redmine * @throws java.io.IOException thrown in case something went wrong while performing I/O * operations * @throws RedmineAuthenticationException thrown in case something went wrong while trying to login * @throws NotFoundException thrown in case the objects requested for could not be found */ @Test public void testCreateAndDeleteIssueCategory() throws RedmineException { Project project = projectManager.getProjectByKey(projectKey); IssueCategory category = IssueCategoryFactory.create(project.getId(), "Category" + new Date().getTime()); category.setAssigneeId(IntegrationTestHelper.getOurUser().getId()); IssueCategory newIssueCategory = issueManager.createCategory(category); assertNotNull("Expected new category not to be null", newIssueCategory); assertNotNull("Expected projectId of new category not to be null", newIssueCategory.getProjectId()); assertNotNull("Expected assignee of new category not to be null", newIssueCategory.getAssigneeId()); assertThat(newIssueCategory.getAssigneeId()).isEqualTo(IntegrationTestHelper.getOurUser().getId()); // now delete category issueManager.deleteCategory(newIssueCategory); // assert that the category is gone List<IssueCategory> categories = issueManager.getCategories(project.getId()); assertTrue( "List of categories of test project must be empty now but is " + categories, categories.isEmpty()); } /** * tests the creation and deletion of a {@link com.taskadapter.redmineapi.bean.IssueCategory} * with the group as assignee * * @throws RedmineException thrown in case something went wrong in Redmine * @throws java.io.IOException thrown in case something went wrong while performing I/O * operations * @throws RedmineAuthenticationException thrown in case something went wrong while trying to login * @throws NotFoundException thrown in case the objects requested for could not be found */ @Test public void testCreateAndDeleteIssueCategoryGroupAssignee() throws RedmineException { Project project = projectManager.getProjectByKey(projectKey); IssueCategory category = IssueCategoryFactory.create(project.getId(), "Category" + new Date().getTime()); category.setAssigneeId(demoGroup.getId()); IssueCategory newIssueCategory = issueManager.createCategory(category); assertNotNull("Expected new category not to be null", newIssueCategory); assertNotNull("Expected projectId of new category not to be null", newIssueCategory.getProjectId()); assertNotNull("Expected assignee of new category not to be null", newIssueCategory.getAssigneeId()); assertThat(newIssueCategory.getAssigneeId()).isEqualTo(demoGroup.getId()); assertThat(newIssueCategory.getAssigneeName()).isEqualTo(demoGroup.getName()); // now delete category issueManager.deleteCategory(newIssueCategory); // assert that the category is gone List<IssueCategory> categories = issueManager.getCategories(project.getId()); assertTrue( "List of categories of test project must be empty now but is " + categories, categories.isEmpty()); } /** * tests the retrieval of {@link IssueCategory}s. * * @throws RedmineException thrown in case something went wrong in Redmine * @throws java.io.IOException thrown in case something went wrong while performing I/O * operations * @throws RedmineAuthenticationException thrown in case something went wrong while trying to login * @throws NotFoundException thrown in case the objects requested for could not be found */ @Test public void testGetIssueCategories() throws RedmineException { Project project = projectManager.getProjectByKey(projectKey); // create some categories IssueCategory testIssueCategory1 = IssueCategoryFactory.create(project.getId(), "Category" + new Date().getTime()); Integer ourUserId = IntegrationTestHelper.getOurUser().getId(); testIssueCategory1.setAssigneeId(ourUserId); IssueCategory newIssueCategory1 = issueManager.createCategory(testIssueCategory1); IssueCategory testIssueCategory2 = IssueCategoryFactory.create(project.getId(), "Category" + new Date().getTime()); testIssueCategory2.setAssigneeId(ourUserId); IssueCategory newIssueCategory2 = issueManager.createCategory(testIssueCategory2); try { List<IssueCategory> categories = issueManager.getCategories(project.getId()); assertEquals("Wrong number of categories for project " + project.getName() + " delivered by Redmine Java API", 2, categories.size()); for (IssueCategory category : categories) { // assert category assertNotNull("ID of category must not be null", category.getId()); assertNotNull("Name of category must not be null", category.getName()); assertNotNull("ProjectId must not be null", category.getProjectId()); assertNotNull("Assignee of category must not be null", category.getAssigneeId()); } } finally { // scrub test categories if (newIssueCategory1 != null) { issueManager.deleteCategory(newIssueCategory1); } if (newIssueCategory2 != null) { issueManager.deleteCategory(newIssueCategory2); } } } /** * tests the creation of an invalid {@link IssueCategory}. * * @throws RedmineException thrown in case something went wrong in Redmine * @throws java.io.IOException thrown in case something went wrong while performing I/O * operations * @throws RedmineAuthenticationException thrown in case something went wrong while trying to login * @throws NotFoundException thrown in case the objects requested for could not be found */ @Test(expected = IllegalArgumentException.class) public void testCreateInvalidIssueCategory() throws RedmineException { IssueCategory category = IssueCategoryFactory.create(null, "InvalidCategory" + new Date().getTime()); issueManager.createCategory(category); } /** * tests the deletion of an invalid {@link IssueCategory}. Expects a * {@link NotFoundException} to be thrown. * * @throws RedmineException thrown in case something went wrong in Redmine * @throws java.io.IOException thrown in case something went wrong while performing I/O * operations * @throws RedmineAuthenticationException thrown in case something went wrong while trying to login * @throws NotFoundException thrown in case the objects requested for could not be found */ @Test(expected = NotFoundException.class) public void testDeleteInvalidIssueCategory() throws RedmineException { // create new test category IssueCategory category = IssueCategoryFactory.create(-1); category.setName("InvalidCategory" + new Date().getTime()); // now try deleting the category issueManager.deleteCategory(category); } /** * Tests the creation and retrieval of an * {@link com.taskadapter.redmineapi.bean.Issue} with a * {@link IssueCategory}. * * @throws RedmineException thrown in case something went wrong in Redmine * @throws java.io.IOException thrown in case something went wrong while performing I/O * operations * @throws RedmineAuthenticationException thrown in case something went wrong while trying to login * @throws NotFoundException thrown in case the objects requested for could not be found */ @Test public void testCreateAndGetIssueWithCategory() throws RedmineException { IssueCategory newIssueCategory = null; Issue newIssue = null; try { Project project = projectManager.getProjectByKey(projectKey); // create an issue category IssueCategory category = IssueCategoryFactory.create(project.getId(), "Category_" + new Date().getTime()); category.setAssigneeId(IntegrationTestHelper.getOurUser().getId()); newIssueCategory = issueManager.createCategory(category); // create an issue Issue issueToCreate = IssueFactory.create(projectId, "getIssueWithCategory_" + UUID.randomUUID()); issueToCreate.setCategory(newIssueCategory); newIssue = issueManager.createIssue(issueToCreate); // retrieve issue Issue retrievedIssue = issueManager.getIssueById(newIssue.getId()); // assert retrieved category of issue IssueCategory retrievedCategory = retrievedIssue.getCategory(); assertNotNull("Category retrieved for issue " + newIssue.getId() + " should not be null", retrievedCategory); assertEquals("ID of category retrieved for issue " + newIssue.getId() + " is wrong", newIssueCategory.getId(), retrievedCategory.getId()); assertEquals("Name of category retrieved for issue " + newIssue.getId() + " is wrong", newIssueCategory.getName(), retrievedCategory.getName()); retrievedIssue.setCategory(null); issueManager.update(retrievedIssue); Issue updatedIssue = issueManager.getIssueById(newIssue.getId()); assertThat(updatedIssue.getCategory()).isNull(); } finally { if (newIssue != null) { issueManager.deleteIssue(newIssue.getId()); } if (newIssueCategory != null) { issueManager.deleteCategory(newIssueCategory); } } } @Test public void nullStartDateIsPreserved() throws RedmineException { Issue issue = IssueFactory.create(projectId, "test start date"); issue.setStartDate(null); Issue newIssue = issueManager.createIssue(issue); Issue loadedIssue = issueManager.getIssueById(newIssue.getId()); assertNull(loadedIssue.getStartDate()); } /** * The custom fields used here MUST ALREADY EXIST on the server and be * associated with the required task type (bug/feature/task/..). * <p/> * See feature request http://www.redmine.org/issues/9664 */ @Test public void testCustomFields() throws Exception { Issue issue = createIssue(issueManager, projectId); // TODO this needs to be reworked, when Redmine gains a real CRUD interface for custom fields // // To test right now the test system needs: // // Custom Field with ID 1 needs to be: // name: my_custom_1 // format: Text (string) // for all project, for all trackers // // Custom Field with ID 2 needs to be: // name: custom_boolean_1 // format: Boolean (bool) // // Custom Field with ID 3 needs to be: // name: custom_multi_list // format: List (list) // multiple values: enabled // possible values: V1, V2, V3 // default value: V2 // // All fields: need to be issue fields, for all project, for all trackers List<CustomFieldDefinition> customFieldDefinitions = mgr.getCustomFieldManager().getCustomFieldDefinitions(); CustomFieldDefinition customField1 = getCustomFieldByName(customFieldDefinitions, "my_custom_1"); CustomFieldDefinition customField2 = getCustomFieldByName(customFieldDefinitions, "custom_boolean_1"); // default empty values assertThat(issue.getCustomFields().size()).isEqualTo(3); issue.clearCustomFields(); String custom1Value = "some value 123"; String custom2Value = "true"; issue.addCustomField(CustomFieldFactory.create(customField1.getId(), customField1.getName(), custom1Value)); issue.addCustomField(CustomFieldFactory.create(customField2.getId(), customField2.getName(), custom2Value)); issueManager.update(issue); Issue updatedIssue = issueManager.getIssueById(issue.getId()); assertThat(updatedIssue.getCustomFields().size()).isEqualTo(3); assertThat(updatedIssue.getCustomFieldByName(customField1.getName()).getValue()).isEqualTo(custom1Value); assertThat(updatedIssue.getCustomFieldByName(customField2.getName()).getValue()).isEqualTo(custom2Value); } @Test public void defaultValueUsedWhenCustomFieldNotProvidedWhenCreatingIssue() throws Exception { Issue newIssue = IssueFactory.create(projectId, "test for custom multi fields"); Issue createdIssue = issueManager.createIssue(newIssue); CustomField customField = createdIssue.getCustomFieldByName("custom_multi_list"); assertThat(customField).isNotNull(); assertThat(customField.getValues().size()).isEqualTo(1); assertThat(customField.getValues().get(0)).isEqualTo("V2"); issueManager.deleteIssue(createdIssue.getId()); } @Test public void setOneValueForMultiLineCustomField() throws Exception { Issue newIssue = IssueFactory.create(projectId, "test for custom multi fields - set one value"); CustomFieldDefinition multiFieldDefinition = loadMultiLineCustomFieldDefinition(); CustomField customField = CustomFieldFactory.create(multiFieldDefinition.getId()); String defaultValue = multiFieldDefinition.getDefaultValue(); customField.setValues(Collections.singletonList(defaultValue)); newIssue.addCustomField(customField); Issue createdIssue = issueManager.createIssue(newIssue); customField = createdIssue.getCustomFieldByName("custom_multi_list"); assertThat(customField).isNotNull(); assertThat(customField.getValues().size()).isEqualTo(1); assertThat(customField.getValues().get(0)).isEqualTo(defaultValue); issueManager.deleteIssue(createdIssue.getId()); } /** * See check for https://github.com/taskadapter/redmine-java-api/issues/54 * * BUG in Redmine 3.0.0: multi-line custom fields values are ignored by Redmine 3.0.0 for new issues * without tracker_id value. * the server ignores values V1, V3 and assigns default V2 value to that multi-line custom field. * I submitted this as http://www.redmine.org/issues/19368 - fixed in Redmine 3.0.1 */ @Test public void setMultiValuesForMultiLineCustomField() throws Exception { Issue issue = IssueFactory.create(projectId, "test for custom multi fields - set multiple values"); CustomFieldDefinition multiFieldDefinition = loadMultiLineCustomFieldDefinition(); CustomField customField = CustomFieldFactory.create(multiFieldDefinition.getId()); customField.setValues(Arrays.asList("V1", "V3")); issue.addCustomField(customField); Issue createdIssue = issueManager.createIssue(issue); CustomField loadedCustomField = createdIssue.getCustomFieldByName("custom_multi_list"); assertThat(loadedCustomField).isNotNull(); assertThat(loadedCustomField.getValues().size()).isEqualTo(2); List<String> values = new ArrayList<>(loadedCustomField.getValues()); Collections.sort(values); assertThat(loadedCustomField.getValues().get(0)).isEqualTo("V1"); assertThat(loadedCustomField.getValues().get(1)).isEqualTo("V3"); issueManager.deleteIssue(createdIssue.getId()); } /** * This is to make sure we have a workaround for a known bug in redmine 2.6. */ @Test public void createIssueWithEmptyListInMultilineCustomFields() throws Exception { Issue newIssue = IssueFactory.create(projectId, "test for custom multi fields - set multiple values"); CustomFieldDefinition multiFieldDefinition = loadMultiLineCustomFieldDefinition(); CustomField customField = CustomFieldFactory.create(multiFieldDefinition.getId()); customField.setValues(Collections.EMPTY_LIST); newIssue.addCustomField(customField); Issue createdIssue = issueManager.createIssue(newIssue); customField = createdIssue.getCustomFieldByName("custom_multi_list"); assertThat(customField).isNotNull(); assertThat(customField.getValues().size()).isEqualTo(0); issueManager.deleteIssue(createdIssue.getId()); } private static CustomFieldDefinition loadMultiLineCustomFieldDefinition() throws RedmineException { List<CustomFieldDefinition> customFieldDefinitions = mgr.getCustomFieldManager().getCustomFieldDefinitions(); return getCustomFieldByName(customFieldDefinitions, "custom_multi_list"); } @Ignore @Test public void testChangesets() throws RedmineException { final Issue issue = issueManager.getIssueById(89, Include.changesets); assertThat(issue.getChangesets().size()).isEqualTo(2); final Changeset firstChange = issue.getChangesets().iterator().next(); assertNotNull(firstChange.getComments()); } /** * Tests the retrieval of {@link Tracker}s. * * @throws RedmineException thrown in case something went wrong in Redmine * @throws RedmineAuthenticationException thrown in case something went wrong while trying to login * @throws NotFoundException thrown in case the objects requested for could not be found */ @Test public void testGetTrackers() throws RedmineException { List<Tracker> trackers = issueManager.getTrackers(); assertNotNull("List of trackers returned should not be null", trackers); assertFalse("List of trackers returned should not be empty", trackers.isEmpty()); for (Tracker tracker : trackers) { assertNotNull("Tracker returned should not be null", tracker); assertNotNull("ID of tracker returned should not be null", tracker.getId()); assertNotNull("Name of tracker returned should not be null", tracker.getName()); } } @Test public void getSavedQueriesDoesNotFailForTempProject() throws RedmineException { issueManager.getSavedQueries(projectKey); } @Test public void getSavedQueriesDoesNotFailForNULLProject() throws RedmineException { issueManager.getSavedQueries(null); } @Ignore("This test requires a specific project configuration") @Test public void testSavedQueries() throws RedmineException { final Collection<SavedQuery> queries = issueManager.getSavedQueries("test"); assertTrue(queries.size() > 0); } @Test public void statusIsUpdated() throws RedmineException { Issue issue = createIssues(issueManager, projectId, 1).get(0); Issue retrievedIssue = issueManager.getIssueById(issue.getId()); Integer initialStatusId = retrievedIssue.getStatusId(); List<IssueStatus> statuses = issueManager.getStatuses(); // get some status ID that is not equal to the initial one Integer newStatusId = null; for (IssueStatus status : statuses) { if (!status.getId().equals(initialStatusId)) { newStatusId = status.getId(); break; } } if (newStatusId == null) { throw new RuntimeException("can't run this test: no Issue Statuses are available except for the initial one"); } retrievedIssue.setStatusId(newStatusId); issueManager.update(retrievedIssue); Issue issueWithUpdatedStatus = issueManager.getIssueById(retrievedIssue.getId()); assertThat(issueWithUpdatedStatus.getStatusId()).isEqualTo(newStatusId); } @Test public void changeProject() throws RedmineException { Project project1 = mgr.getProjectManager().getProjectByKey(projectKey); Project project2 = mgr.getProjectManager().getProjectByKey(projectKey2); Issue issue = createIssue(issueManager, projectId); Issue retrievedIssue = issueManager.getIssueById(issue.getId()); assertThat(retrievedIssue.getProjectId()).isEqualTo(project1.getId()); issue.setProjectId(project2.getId()); issueManager.update(issue); retrievedIssue = issueManager.getIssueById(issue.getId()); assertThat(retrievedIssue.getProjectId()).isEqualTo(project2.getId()); deleteIssueIfNotNull(issue); } @Test public void issueAssignmentUserAndGroup() throws RedmineException { Issue issue = createIssue(issueManager, projectId); assertNull(issue.getAssigneeId()); issue.setAssigneeId(IntegrationTestHelper.getOurUser().getId()); issueManager.update(issue); Issue retrievedIssue = issueManager.getIssueById(issue.getId()); // User assignment succeeded assertThat(retrievedIssue.getAssigneeId()).isEqualTo(IntegrationTestHelper.getOurUser().getId()); issue.setAssigneeId(demoGroup.getId()); issueManager.update(issue); retrievedIssue = issueManager.getIssueById(issue.getId()); // Group assignment succeeded assertThat(retrievedIssue.getAssigneeId()).isEqualTo(demoGroup.getId()); deleteIssueIfNotNull(issue); } @Test public void issueCanBeCreatedOnBehalfOfAnotherUser() throws RedmineException { final User newUser = userManager.createUser(UserGenerator.generateRandomUser()); Issue issue = null; try { RedmineManager managerOnBehalfOfUser = IntegrationTestHelper.createRedmineManager(); managerOnBehalfOfUser.setOnBehalfOfUser(newUser.getLogin()); issue = createIssue(managerOnBehalfOfUser.getIssueManager(), projectId); assertThat(issue.getAuthorName()).isEqualTo(newUser.getFullName()); } finally { userManager.deleteUser(newUser.getId()); deleteIssueIfNotNull(issue); } } @Test public void issuesCanBeFoundByFreeFormSearch() throws RedmineException { // create some random issues in the project createIssues(issueManager, projectId, 3); final String subject = "test for free_form_search."; final Issue issueToCreate = IssueFactory.create(projectId, subject); Integer createdIssueId = null; try { createdIssueId = issueManager.createIssue(issueToCreate).getId(); Map<String, String> params = new HashMap<>(); params.put("project_id", Integer.toString(projectId)); params.put("subject", "~free_form_search"); List<Issue> issues = issueManager.getIssues(params).getResults(); assertThat(issues.size()).isEqualTo(1); final Issue loaded = issues.get(0); assertThat(loaded.getSubject()).isEqualTo(subject); } finally { issueManager.deleteIssue(createdIssueId); } } /** * regression test for https://github.com/taskadapter/redmine-java-api/issues/12 and * https://github.com/taskadapter/redmine-java-api/issues/215 */ @Test public void issuesCanBeFoundByMultiQuerySearch() throws RedmineException { final Issue issue1 = IssueFactory.create(projectId, "summary 1 here"); issueManager.createIssue(issue1); final Issue issue2 = IssueFactory.create(projectId, "summary 2 here"); issueManager.createIssue(issue2); // have some random subject to avoid collisions with other tests String subject = "another" + new Random().nextInt(); final Issue issue3 = IssueFactory.create(projectId, subject); issueManager.createIssue(issue3); final User currentUser = userManager.getCurrentUser(); Params params = new Params() .add("set_filter", "1") .add("f[]", "subject") .add("op[subject]", "~") .add("v[subject][]", subject) .add("f[]", "author_id") .add("op[author_id]", "~") .add("v[author_id][]", currentUser.getId()+""); final ResultsWrapper<Issue> list = issueManager.getIssues(params); // only 1 issue must be found assertThat(list.getResults()).hasSize(1); } private void deleteIssueIfNotNull(Issue issue) throws RedmineException { if (issue != null) { issueManager.deleteIssue(issue.getId()); } } }