1
0
Fork 0

Explode Issue attributes

master
Pierre-Luc Dupont 2016-06-01 16:27:50 -04:00
parent cbcf089722
commit 04f90c00d1
22 changed files with 1249 additions and 201 deletions

View File

@ -279,30 +279,27 @@ public class Example {
https://docs.atlassian.com/jira-software/REST/cloud/
### Agile supported calls ###
1. [AgileClient](src/main/java/net/rcarz/jiraclient/agile/AgileClient.java)
1. GET /rest/agile/1.0/board
1. GET /rest/agile/1.0/board/{boardId}
1. GET /rest/agile/1.0/sprint/{sprintId}
1. GET /rest/agile/1.0/issue/{issueIdOrKey}
1. [Board](src/main/java/net/rcarz/jiraclient/agile/Board.java)
1. GET /rest/agile/1.0/board
1. GET /rest/agile/1.0/board/{boardId}
1. GET /rest/agile/1.0/board/{boardId}/sprint
1. [Sprint](src/main/java/net/rcarz/jiraclient/agile/Sprint.java)
1. GET /rest/agile/1.0/sprint/{sprintId}
1. GET /rest/agile/1.0/board/{boardId}/sprint
1. [Issue](src/main/java/net/rcarz/jiraclient/agile/Issue.java)
1. GET /rest/agile/1.0/issue/{issueIdOrKey}
1. To implement
1. -- GET /rest/agile/1.0/board/{boardId}/backlog
1. -- GET /rest/agile/1.0/board/{boardId}/epic
1. -- GET /rest/agile/1.0/board/{boardId}/epic/{epicId}/issue
1. -- GET /rest/agile/1.0/board/{boardId}/epic/none/issue
1. -- GET /rest/agile/1.0/board/{boardId}/sprint/{sprintId}/issue
1. -- GET /rest/agile/1.0/epic/{epicIdOrKey}/issue
1. -- GET /rest/agile/1.0/epic/none/issue
1. -- GET /rest/agile/1.0/sprint/{sprintId}/issue
| Class | Method | REST Call |
| ----- | ------ | --------- |
| [AgileClient](src/main/java/net/rcarz/jiraclient/agile/AgileClient.java) | ```List<Board> getBoards()``` | GET /rest/agile/1.0/board |
| | ```Board getBoard(long id)``` | GET /rest/agile/1.0/board/{boardId} |
| | ```Sprint getSprint(long id)``` | GET /rest/agile/1.0/sprint/{sprintId} |
| | ```Epic getEpic(long id)``` | GET /rest/agile/1.0/epic/{epicId} |
| | ```Issue getIssue(long id)``` | GET /rest/agile/1.0/issue/{issueId} |
| | ```Issue getIssue(String key)``` | GET /rest/agile/1.0/issue/{issueKey} |
| [Board](src/main/java/net/rcarz/jiraclient/agile/Board.java) | ``` static List<Board> getAll(RestClient restclient)``` | GET /rest/agile/1.0/board |
| | ```static Board get(RestClient restclient, long id)``` | GET /rest/agile/1.0/board/{boardId} |
| | ```List<Sprint> getSprints()``` | GET /rest/agile/1.0/board/{boardId}/sprint |
| * | ```List<Epic> getEpics()``` | GET /rest/agile/1.0/board/{boardId}/epic
| * | ```List<Issue> getBacklog()``` | GET /rest/agile/1.0/board/{boardId}/backlog
| * | ```List<Issue> getIssuesWithoutEpic()``` | GET /rest/agile/1.0/board/{boardId}/epic/none/issue
| [Sprint](src/main/java/net/rcarz/jiraclient/agile/Sprint.java) | ``` static Sprint get(RestClient restclient, long sprintId)``` | GET /rest/agile/1.0/sprint/{sprintId} |
| | ```static List<Sprint> getAll(RestClient restclient, long boardId)``` | GET /rest/agile/1.0/board/{boardId}/sprint |
| * | ```List<Issue> getIssues()``` | GET /rest/agile/1.0/sprint/{sprintId}/issue |
| [Epic](src/main/java/net/rcarz/jiraclient/agile/Epic.java) | ```static Epic get(RestClient restclient, long id)``` | GET /rest/agile/1.0/epic/{epicId} |
| * | ```List<Issue> getIssues()``` | GET /rest/agile/1.0/epic/{epicId}/issue |
| [Issue](src/main/java/net/rcarz/jiraclient/agile/Issue.java) | ```static Issue get(RestClient restclient, long id)``` | GET /rest/agile/1.0/issue/{issueId} |
| | ```static Issue get(RestClient restclient, String key)``` | GET /rest/agile/1.0/issue/{issueKey} |

View File

@ -28,6 +28,7 @@ import java.util.List;
/**
* An Agile extension to the JIRA client.
*
* @author pldupont
* @see "https://docs.atlassian.com/jira-software/REST/cloud/"
*/
public class AgileClient {

View File

@ -25,18 +25,16 @@ import net.rcarz.jiraclient.RestClient;
import net.sf.json.JSON;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.math.NumberUtils;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* A base class for Agile resources.
*
* @author pldupont
* @see "https://docs.atlassian.com/jira-software/REST/cloud/"
*/
public abstract class AgileResource {
@ -51,15 +49,16 @@ public abstract class AgileResource {
private long id = 0;
private String name;
private String self;
private Map<String, Object> attributes = new HashMap<String, Object>();
private JSONObject attributes = new JSONObject();
/**
* Creates a new Agile resource.
*
* @param restclient REST client instance
* @param json JSON payload
* @throws JiraException when the retrieval fails
*/
public AgileResource(RestClient restclient, JSONObject json) {
public AgileResource(RestClient restclient, JSONObject json) throws JiraException {
this.restclient = restclient;
if (json != null) {
deserialize(json);
@ -73,8 +72,9 @@ public abstract class AgileResource {
* @param r a JSONObject instance
* @param restclient REST client instance
* @return a Resource instance or null if r isn't a JSONObject instance
* @throws JiraException when the retrieval fails
*/
private static <T extends AgileResource> T getResource(
protected static <T extends AgileResource> T getResource(
Class<T> type, Object r, RestClient restclient) throws JiraException {
if (!(r instanceof JSONObject)) {
@ -101,26 +101,29 @@ public abstract class AgileResource {
* @param type Resource data type
* @param ra a JSONArray instance
* @param restclient REST client instance
* @param listName The name of the list of items from the JSON result.
* @return a list of Resources found in ra
* @throws JiraException when the retrieval fails
*/
private static <T extends AgileResource> List<T> getResourceArray(
Class<T> type, Object ra, RestClient restclient) throws JiraException {
protected static <T extends AgileResource> List<T> getResourceArray(
Class<T> type, Object ra, RestClient restclient, String listName) throws JiraException {
if (!(ra instanceof JSONObject)) {
throw new JiraException("JSON payload is malformed");
}
JSONObject jo = (JSONObject) ra;
if (!jo.containsKey("values") || !(jo.get("values") instanceof JSONArray)) {
if (!jo.containsKey(listName) || !(jo.get(listName) instanceof JSONArray)) {
throw new JiraException(type.getSimpleName() + " result is malformed");
}
List<T> results = new ArrayList<T>();
for (Object v : (JSONArray) jo.get("values")) {
for (Object v : (JSONArray) jo.get(listName)) {
T item = getResource(type, v, restclient);
if (item != null)
if (item != null) {
results.add(item);
}
}
return results;
@ -130,10 +133,28 @@ public abstract class AgileResource {
* Retrieves all boards visible to the session user.
*
* @param restclient REST client instance
* @param type The type of the object to deserialize.
* @param url The URL to call.
* @return a list of boards
* @throws JiraException when the retrieval fails
*/
static <T extends AgileResource> List<T> list(RestClient restclient, Class<T> type, String url) throws JiraException {
static <T extends AgileResource> List<T> list(
RestClient restclient, Class<T> type, String url) throws JiraException {
return list(restclient, type, url, "values");
}
/**
* Retrieves all boards visible to the session user.
*
* @param restclient REST client instance
* @param type The type of the object to deserialize.
* @param url The URL to call.
* @param listName The name of the list of items in the JSON response.
* @return a list of boards
* @throws JiraException when the retrieval fails
*/
static <T extends AgileResource> List<T> list(
RestClient restclient, Class<T> type, String url, String listName) throws JiraException {
JSON result;
try {
@ -145,7 +166,8 @@ public abstract class AgileResource {
return getResourceArray(
type,
result,
restclient
restclient,
listName
);
}
@ -172,6 +194,44 @@ public abstract class AgileResource {
);
}
/**
* Extract from a sub list the Resource array, if present.
*
* @param type Resource data type
* @param subJson a JSONObject instance
* @param resourceName The name of the list of items from the JSON result.
* @param <T> The type of Agile resource to return.
* @return The list of resources if present.
* @throws JiraException when the retrieval fails
*/
<T extends AgileResource> List<T> getSubResourceArray(
Class<T> type, JSONObject subJson, String resourceName) throws JiraException {
List<T> result = null;
if (subJson.containsKey(resourceName)) {
result = getResourceArray(type, subJson.get(resourceName), getRestclient(), resourceName + "s");
}
return result;
}
/**
* Extract from a sub list the Resource, if present.
*
* @param type Resource data type
* @param subJson a JSONObject instance
* @param resourceName The name of the item from the JSON result.
* @param <T> The type of Agile resource to return.
* @return The resource if present.
* @throws JiraException when the retrieval fails
*/
<T extends AgileResource> T getSubResource(
Class<T> type, JSONObject subJson, String resourceName) throws JiraException {
T result = null;
if (subJson.containsKey(resourceName)) {
result = getResource(type, subJson.get(resourceName), getRestclient());
}
return result;
}
/**
* @return Internal JIRA ID.
*/
@ -186,6 +246,13 @@ public abstract class AgileResource {
return name;
}
/**
* @param name Setter for the resource name. In some case, the name is called something else.
*/
void setName(String name) {
this.name = name;
}
/**
* @return The resource URL.
*/
@ -206,47 +273,36 @@ public abstract class AgileResource {
* @param name The name of the attribute to retrieve.
* @return The value of the attribute.
*/
String getAttribute(String name) {
public Object getAttribute(String name) {
return (String) attributes.get(name);
}
/**
* Retrieve the specified attribute as a generic object.
*
* @param name The name of the attribute to retrieve.
* @return The value of the attribute.
*/
int getAttributeAsInt(String name) {
return NumberUtils.toInt(getAttribute(name), 0);
}
/**
* Retrieve the specified attribute as a generic object.
*
* @param name The name of the attribute to retrieve.
* @return The value of the attribute.
*/
boolean getAttributeAsBoolean(String name) {
return BooleanUtils.toBoolean(getAttribute(name));
}
/**
* Deserialize the json to extract standard attributes and keep a reference of
* other attributes.
*
* @param json The JSON object to read.
*/
protected void deserialize(JSONObject json) {
void deserialize(JSONObject json) throws JiraException {
id = getLong(json.get("id"));
name = Field.getString(json.get("name"));
self = Field.getString(json.get("self"));
addAttributes(json);
}
/**
* Allow to add more attributes.
*
* @param json The json object to extract attributes from.
*/
void addAttributes(JSONObject json) {
attributes.putAll(json);
}
long getLong(Object o) {
if (o instanceof Integer || o instanceof Long) {
return Field.getInteger(o);
return Field.getLong(o);
} else if (o instanceof String && NumberUtils.isDigits((String) o)) {
return NumberUtils.toLong((String) o, 0L);
} else {

View File

@ -33,8 +33,6 @@ import java.util.List;
*/
public class Board extends AgileResource {
private static final String ATTR_TYPE = "type";
private String type;
/**
@ -43,7 +41,7 @@ public class Board extends AgileResource {
* @param restclient REST client instance
* @param json JSON payload
*/
protected Board(RestClient restclient, JSONObject json) {
protected Board(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
@ -71,9 +69,9 @@ public class Board extends AgileResource {
}
@Override
protected void deserialize(JSONObject json) {
protected void deserialize(JSONObject json) throws JiraException {
super.deserialize(json);
type = Field.getString(json.get(ATTR_TYPE));
type = Field.getString(json.get("type"));
}
/**
@ -91,15 +89,28 @@ public class Board extends AgileResource {
return Sprint.getAll(getRestclient(), getId());
}
// /**
// * Retrieves the backlog data for this rapid view.
// *
// * @return the backlog
// *
// * @throws JiraException when the retrieval fails
// */
// public Backlog getBacklogData() throws JiraException {
// return Backlog.get(restclient, this);
// }
/**
* @return All issues in the Board backlog.
* @throws JiraException when the retrieval fails
*/
public List<Issue> getBacklog() throws JiraException {
return AgileResource.list(getRestclient(), Issue.class, RESOURCE_URI + "board/" + getId() + "/backlog", "issues");
}
/**
* @return All issues without epic in the Board .
* @throws JiraException when the retrieval fails
*/
public List<Issue> getIssuesWithoutEpic() throws JiraException {
return AgileResource.list(getRestclient(), Issue.class, RESOURCE_URI + "board/" + getId() + "/epic/none/issue", "issues");
}
/**
* @return All epics associated to the Board.
* @throws JiraException when the retrieval fails
*/
public List<Epic> getEpics() throws JiraException {
return AgileResource.list(getRestclient(), Epic.class, RESOURCE_URI + "board/" + getId() + "/epic");
}
}

View File

@ -1,10 +1,32 @@
/**
* jira-client - a simple JIRA REST client
* Copyright (c) 2013 Bob Carroll (bob.carroll@alum.rit.edu)
* <p>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* <p>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* <p>
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.rcarz.jiraclient.agile;
import net.rcarz.jiraclient.JiraException;
import net.rcarz.jiraclient.RestClient;
import net.sf.json.JSONObject;
/**
* Created by pldupont on 2016-05-20.
* Represents an Agile Comment.
*
* @author pldupont
*/
public class Comment extends AgileResource {
@ -14,7 +36,7 @@ public class Comment extends AgileResource {
* @param restclient REST client instance
* @param json JSON payload
*/
public Comment(RestClient restclient, JSONObject json) {
public Comment(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
}

View File

@ -1,22 +1,46 @@
/**
* jira-client - a simple JIRA REST client
* Copyright (c) 2013 Bob Carroll (bob.carroll@alum.rit.edu)
* <p>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* <p>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* <p>
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.rcarz.jiraclient.agile;
import net.rcarz.jiraclient.JiraException;
import net.rcarz.jiraclient.RestClient;
import net.sf.json.JSONObject;
import java.util.List;
/**
* Created on 2016-05-20.
* Represents an Agile Epic.
*
* @author pldupont
*/
public class Epic extends AgileResource {
private Issue issue;
/**
* Creates a new Agile resource.
*
* @param restclient REST client instance
* @param json JSON payload
*/
public Epic(RestClient restclient, JSONObject json) {
public Epic(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
@ -31,4 +55,24 @@ public class Epic extends AgileResource {
public static Epic get(RestClient restclient, long id) throws JiraException {
return AgileResource.get(restclient, Epic.class, RESOURCE_URI + "epic/" + id);
}
/**
* @param refresh If true, will fetch the information from JIRA, otherwise use the cached info.
* @return The Issue representation of this Epic.
* @throws JiraException when the retrieval fails
*/
public Issue asIssue(boolean refresh) throws JiraException {
if (this.issue == null || refresh) {
this.issue = Issue.get(getRestclient(), getId());
}
return this.issue;
}
/**
* @return All issues in the Epic.
* @throws JiraException when the retrieval fails
*/
public List<Issue> getIssues() throws JiraException {
return AgileResource.list(getRestclient(), Issue.class, RESOURCE_URI + "epic/" + getId() + "/issue", "issues");
}
}

View File

@ -1,22 +1,68 @@
/**
* jira-client - a simple JIRA REST client
* Copyright (c) 2013 Bob Carroll (bob.carroll@alum.rit.edu)
* <p>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* <p>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* <p>
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.rcarz.jiraclient.agile;
import net.rcarz.jiraclient.Field;
import net.rcarz.jiraclient.JiraException;
import net.rcarz.jiraclient.RestClient;
import net.sf.json.JSONObject;
import java.util.Date;
import java.util.List;
/**
* Created on 2016-05-20.
* Represents an Agile Issue.
*
* @author pldupont
*/
public class Issue extends AgileResource {
private String key;
private boolean flagged;
private Sprint sprint;
private List<Sprint> closedSprints;
private String description;
private Project project;
private List<Comment> comments;
private Epic epic;
private List<Worklog> worklogs;
private TimeTracking timeTracking;
private IssueType issueType;
private Status status;
private Resolution resolution;
private Date created;
private Date updated;
private Priority priority;
private User assignee;
private User creator;
private User reporter;
private String environment;
/**
* Creates a new Agile Issue resource.
*
* @param restclient REST client instance
* @param json JSON payload
*/
public Issue(RestClient restclient, JSONObject json) {
public Issue(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
@ -43,4 +89,117 @@ public class Issue extends AgileResource {
public static Issue get(RestClient restclient, String key) throws JiraException {
return AgileResource.get(restclient, Issue.class, RESOURCE_URI + "issue/" + key);
}
@Override
protected void deserialize(JSONObject json) throws JiraException {
super.deserialize(json);
this.key = Field.getString(json.get("key"));
// Extract from Field sub JSONObject
if (json.containsKey("fields")) {
JSONObject fields = (JSONObject) json.get("fields");
setName(Field.getString(fields.get("summary")));
this.flagged = Field.getBoolean(fields.get("flagged"));
this.sprint = getSubResource(Sprint.class, fields, "sprint");
this.closedSprints = getSubResourceArray(Sprint.class, fields, "closedSprint");
this.description = Field.getString(fields.get("description"));
this.project = getSubResource(Project.class, fields, "project");
this.comments = getSubResourceArray(Comment.class, fields, "comment");
this.epic = getSubResource(Epic.class, fields, "epic");
this.worklogs = getSubResourceArray(Worklog.class, fields, "worklog");
this.timeTracking = getSubResource(TimeTracking.class, fields, "timetracking");
this.environment = Field.getString(fields.get("environment"));
this.issueType = getSubResource(IssueType.class, fields, "issuetype");
this.status = getSubResource(Status.class, fields, "status");
this.resolution = getSubResource(Resolution.class, fields, "resolution");
this.created = Field.getDateTime(fields.get("created"));
this.updated = Field.getDateTime(fields.get("updated"));
this.priority = getSubResource(Priority.class, fields, "priority");
this.assignee = getSubResource(User.class, fields, "assignee");
this.creator = getSubResource(User.class, fields, "creator");
this.reporter = getSubResource(User.class, fields, "reporter");
addAttributes(fields);
}
}
public String getKey() {
return key;
}
public boolean isFlagged() {
return flagged;
}
public Sprint getSprint() {
return sprint;
}
public List<Sprint> getClosedSprints() {
return closedSprints;
}
public String getDescription() {
return description;
}
public Project getProject() {
return project;
}
public List<Comment> getComments() {
return comments;
}
public Epic getEpic() {
return epic;
}
public List<Worklog> getWorklogs() {
return worklogs;
}
public TimeTracking getTimeTracking() {
return timeTracking;
}
public IssueType getIssueType() {
return issueType;
}
public Status getStatus() {
return status;
}
public Resolution getResolution() {
return resolution;
}
public Date getCreated() {
return created;
}
public Date getUpdated() {
return updated;
}
public Priority getPriority() {
return priority;
}
public User getAssignee() {
return assignee;
}
public User getCreator() {
return creator;
}
public User getReporter() {
return reporter;
}
public String getEnvironment() {
return environment;
}
}

View File

@ -0,0 +1,42 @@
/**
* jira-client - a simple JIRA REST client
* Copyright (c) 2013 Bob Carroll (bob.carroll@alum.rit.edu)
* <p>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* <p>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* <p>
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.rcarz.jiraclient.agile;
import net.rcarz.jiraclient.JiraException;
import net.rcarz.jiraclient.RestClient;
import net.sf.json.JSONObject;
/**
* Represents an Agile IssueType.
*
* @author pldupont
*/
public class IssueType extends AgileResource {
/**
* Creates a new Agile resource.
*
* @param restclient REST client instance
* @param json JSON payload
*/
public IssueType(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
}

View File

@ -0,0 +1,42 @@
/**
* jira-client - a simple JIRA REST client
* Copyright (c) 2013 Bob Carroll (bob.carroll@alum.rit.edu)
* <p>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* <p>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* <p>
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.rcarz.jiraclient.agile;
import net.rcarz.jiraclient.JiraException;
import net.rcarz.jiraclient.RestClient;
import net.sf.json.JSONObject;
/**
* Represents an Agile Priority.
*
* @author pldupont
*/
public class Priority extends AgileResource {
/**
* Creates a new Agile resource.
*
* @param restclient REST client instance
* @param json JSON payload
*/
public Priority(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
}

View File

@ -1,10 +1,32 @@
/**
* jira-client - a simple JIRA REST client
* Copyright (c) 2013 Bob Carroll (bob.carroll@alum.rit.edu)
* <p>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* <p>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* <p>
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.rcarz.jiraclient.agile;
import net.rcarz.jiraclient.JiraException;
import net.rcarz.jiraclient.RestClient;
import net.sf.json.JSONObject;
/**
* Created by pldupont on 2016-05-20.
* Represents an Agile Project.
*
* @author pldupont
*/
public class Project extends AgileResource {
@ -14,7 +36,7 @@ public class Project extends AgileResource {
* @param restclient REST client instance
* @param json JSON payload
*/
public Project(RestClient restclient, JSONObject json) {
public Project(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
}

View File

@ -0,0 +1,42 @@
/**
* jira-client - a simple JIRA REST client
* Copyright (c) 2013 Bob Carroll (bob.carroll@alum.rit.edu)
* <p>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* <p>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* <p>
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.rcarz.jiraclient.agile;
import net.rcarz.jiraclient.JiraException;
import net.rcarz.jiraclient.RestClient;
import net.sf.json.JSONObject;
/**
* Represents an Agile Resolution.
*
* @author pldupont
*/
public class Resolution extends AgileResource {
/**
* Creates a new Agile resource.
*
* @param restclient REST client instance
* @param json JSON payload
*/
public Resolution(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
}

View File

@ -34,12 +34,6 @@ import java.util.List;
*/
public class Sprint extends AgileResource {
private static final String ATTR_STATE = "state";
private static final String ATTR_ORIGIN_BOARD_ID = "originBoardId";
private static final String ATTR_START_DATE = "startDate";
private static final String ATTR_END_DATE = "endDate";
private static final String ATTR_COMPLETE_DATE = "completeDate";
private String state;
private long originBoardId;
private Date startDate;
@ -52,7 +46,7 @@ public class Sprint extends AgileResource {
* @param restclient REST client instance
* @param json JSON payload
*/
protected Sprint(RestClient restclient, JSONObject json) {
protected Sprint(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
@ -80,14 +74,22 @@ public class Sprint extends AgileResource {
return AgileResource.list(restclient, Sprint.class, RESOURCE_URI + "board/" + boardId + "/sprint");
}
/**
* @return All issues in the Sprint.
* @throws JiraException when the retrieval fails
*/
public List<Issue> getIssues() throws JiraException {
return AgileResource.list(getRestclient(), Issue.class, RESOURCE_URI + "sprint/" + getId() + "/issue", "issues");
}
@Override
protected void deserialize(JSONObject json) {
protected void deserialize(JSONObject json) throws JiraException {
super.deserialize(json);
state = Field.getString(json.get(ATTR_STATE));
originBoardId = getLong(json.get(ATTR_ORIGIN_BOARD_ID));
startDate = Field.getDateTime(json.get(ATTR_START_DATE));
endDate = Field.getDateTime(json.get(ATTR_END_DATE));
completeDate = Field.getDateTime(json.get(ATTR_COMPLETE_DATE));
state = Field.getString(json.get("state"));
originBoardId = getLong(json.get("originBoardId"));
startDate = Field.getDateTime(json.get("startDate"));
endDate = Field.getDateTime(json.get("endDate"));
completeDate = Field.getDateTime(json.get("completeDate"));
}
public String getState() {

View File

@ -0,0 +1,42 @@
/**
* jira-client - a simple JIRA REST client
* Copyright (c) 2013 Bob Carroll (bob.carroll@alum.rit.edu)
* <p>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* <p>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* <p>
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.rcarz.jiraclient.agile;
import net.rcarz.jiraclient.JiraException;
import net.rcarz.jiraclient.RestClient;
import net.sf.json.JSONObject;
/**
* Represents an Agile Status.
*
* @author pldupont
*/
public class Status extends AgileResource {
/**
* Creates a new Agile resource.
*
* @param restclient REST client instance
* @param json JSON payload
*/
public Status(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
}

View File

@ -1,10 +1,32 @@
/**
* jira-client - a simple JIRA REST client
* Copyright (c) 2013 Bob Carroll (bob.carroll@alum.rit.edu)
* <p>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* <p>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* <p>
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.rcarz.jiraclient.agile;
import net.rcarz.jiraclient.JiraException;
import net.rcarz.jiraclient.RestClient;
import net.sf.json.JSONObject;
/**
* Created by pldupont on 2016-05-20.
* Represents an Agile TimeTracking.
*
* @author pldupont
*/
public class TimeTracking extends AgileResource {
@ -14,7 +36,7 @@ public class TimeTracking extends AgileResource {
* @param restclient REST client instance
* @param json JSON payload
*/
public TimeTracking(RestClient restclient, JSONObject json) {
public TimeTracking(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
}

View File

@ -0,0 +1,42 @@
/**
* jira-client - a simple JIRA REST client
* Copyright (c) 2013 Bob Carroll (bob.carroll@alum.rit.edu)
* <p>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* <p>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* <p>
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.rcarz.jiraclient.agile;
import net.rcarz.jiraclient.JiraException;
import net.rcarz.jiraclient.RestClient;
import net.sf.json.JSONObject;
/**
* Represents an Agile User.
*
* @author pldupont
*/
public class User extends AgileResource {
/**
* Creates a new Agile resource.
*
* @param restclient REST client instance
* @param json JSON payload
*/
public User(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
}

View File

@ -1,10 +1,32 @@
/**
* jira-client - a simple JIRA REST client
* Copyright (c) 2013 Bob Carroll (bob.carroll@alum.rit.edu)
* <p>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* <p>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* <p>
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.rcarz.jiraclient.agile;
import net.rcarz.jiraclient.JiraException;
import net.rcarz.jiraclient.RestClient;
import net.sf.json.JSONObject;
/**
* Created by pldupont on 2016-05-20.
* Represents an Agile Worklog.
*
* @author pldupont
*/
public class Worklog extends AgileResource {
@ -14,7 +36,7 @@ public class Worklog extends AgileResource {
* @param restclient REST client instance
* @param json JSON payload
*/
public Worklog(RestClient restclient, JSONObject json) {
public Worklog(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
}

View File

@ -72,11 +72,111 @@ class AbstractResourceTest {
}
static void "Assert equals to Project 10000"(Project project) {
assertThat project, new IsNot<>(new IsNull())
assertThat project.getId(), new IsEqual<Long>(JSONResources.PROJECT_ID)
assertThat project.getName(), new IsEqual<String>(JSONResources.PROJECT_NAME)
assertThat project.getSelfURL(), new IsEqual<String>(JSONResources.PROJECT_SELF)
}
static void "Assert equals to Comment 9999"(Comment comment) {
assertThat comment, new IsNot<>(new IsNull())
assertThat comment.getId(), new IsEqual<Long>(JSONResources.ISSUE_COMMENT_ID)
assertThat comment.getName(), new IsNull<String>()
assertThat comment.getSelfURL(), new IsEqual<String>(JSONResources.ISSUE_COMMENT_SELF)
}
static void "Assert equals to TimeTracking"(TimeTracking timeTracking) {
assertThat timeTracking, new IsNot<>(new IsNull())
assertThat timeTracking.getId(), new IsEqual<Long>(0L)
assertThat timeTracking.getName(), new IsNull<String>()
assertThat timeTracking.getSelfURL(), new IsNull<String>()
}
static void "Assert equals to IssueType"(IssueType issueType) {
assertThat issueType, new IsNot<>(new IsNull())
assertThat issueType.getId(), new IsEqual<Long>(JSONResources.ISSUE_TYPE_ID)
assertThat issueType.getName(), new IsEqual<String>(JSONResources.ISSUE_TYPE_NAME)
assertThat issueType.getSelfURL(), new IsEqual<String>(JSONResources.ISSUE_TYPE_SELF)
}
static void "Assert equals to Status"(Status status) {
assertThat status, new IsNot<>(new IsNull())
assertThat status.getId(), new IsEqual<Long>(JSONResources.ISSUE_STATUS_ID)
assertThat status.getName(), new IsEqual<String>(JSONResources.ISSUE_STATUS_NAME)
assertThat status.getSelfURL(), new IsEqual<String>(JSONResources.ISSUE_STATUS_SELF)
}
static void "Assert equals to Resolution"(Resolution resolution) {
assertThat resolution, new IsNot<>(new IsNull())
assertThat resolution.getId(), new IsEqual<Long>(JSONResources.ISSUE_RESOLUTION_ID)
assertThat resolution.getName(), new IsEqual<String>(JSONResources.ISSUE_RESOLUTION_NAME)
assertThat resolution.getSelfURL(), new IsEqual<String>(JSONResources.ISSUE_RESOLUTION_SELF)
}
static void "Assert equals to Priority"(Priority priority) {
assertThat priority, new IsNot<>(new IsNull())
assertThat priority.getId(), new IsEqual<Long>(JSONResources.ISSUE_PRIORITY_ID)
assertThat priority.getName(), new IsEqual<String>(JSONResources.ISSUE_PRIORITY_NAME)
assertThat priority.getSelfURL(), new IsEqual<String>(JSONResources.ISSUE_PRIORITY_SELF)
}
static void "Assert equals to User"(User user) {
assertThat user, new IsNot<>(new IsNull())
assertThat user.getId(), new IsEqual<Long>(0L)
assertThat user.getName(), new IsEqual<String>(JSONResources.USER_NAME)
assertThat user.getSelfURL(), new IsEqual<String>(JSONResources.USER_SELF)
}
static void "Assert equals to Worklog 100028"(Worklog worklog) {
assertThat worklog, new IsNot<>(new IsNull())
assertThat worklog.getId(), new IsEqual<Long>(JSONResources.ISSUE_WORKLOG_ID)
assertThat worklog.getName(), new IsNull<String>()
assertThat worklog.getSelfURL(), new IsEqual<String>(JSONResources.ISSUE_WORKLOG_SELF)
}
static void "Assert equals to Issue 10001"(Issue issue) {
assertThat issue, new IsNot<>(new IsNull())
assertThat issue.getId(), new IsEqual<Long>(JSONResources.ISSUE_ID)
assertThat issue.getName(), new IsNull<String>()
assertThat issue.getSelfURL(), new IsEqual<String>(JSONResources.ISSUE_SELF)
assertThat issue.getKey(), new IsEqual<String>(JSONResources.ISSUE_KEY)
assertThat issue.isFlagged(), new IsEqual<Boolean>(JSONResources.ISSUE_FLAGGED)
"Assert equals to Sprint ${issue.getSprint().getId()}"(issue.getSprint())
assertThat issue.getClosedSprints(), new IsNot<>(new IsNull<>())
assertThat issue.getClosedSprints().size(), new IsEqual<Integer>(3)
assertThat issue.getDescription(), new IsEqual<String>(JSONResources.ISSUE_DESCRIPTION)
"Assert equals to Project ${issue.getProject().getId()}"(issue.getProject())
assertThat issue.getComments(), new IsNot<>(new IsNull<>())
assertThat issue.getComments().size(), new IsEqual<Integer>(1)
"Assert equals to Comment ${issue.getComments().get(0).getId()}"(issue.getComments().get(0))
"Assert equals to Epic ${issue.getEpic().getId()}"(issue.getEpic())
"Assert equals to TimeTracking"(issue.getTimeTracking())
assertThat issue.getWorklogs(), new IsNot<>(new IsNull<>())
assertThat issue.getWorklogs().size(), new IsEqual<Integer>(1)
"Assert equals to Worklog ${issue.getWorklogs().get(0).getId()}"(issue.getWorklogs().get(0))
assertThat issue.getEnvironment(), new IsEqual<String>(JSONResources.ISSUE_ENVIRONMENT)
"Assert equals to IssueType"(issue.getIssueType())
"Assert equals to Status"(issue.getStatus())
"Assert equals to Resolution"(issue.getResolution())
assertThat issue.getCreated(), new IsEqual<Date>(JSONResources.ISSUE_CREATED)
assertThat issue.getUpdated(), new IsEqual<Date>(JSONResources.ISSUE_UPDATED)
"Assert equals to User"(issue.getAssignee())
"Assert equals to User"(issue.getCreator())
"Assert equals to User"(issue.getReporter())
"Assert equals to Priority"(issue.getPriority())
}
static void "Assert equals to Issue 10010"(Issue issue) {
assertThat issue, new IsNot<>(new IsNull())
assertThat issue.getId(), new IsEqual<Long>(JSONResources.BLANK_ISSUE1_ID)
assertThat issue.getName(), new IsNull<String>()
assertThat issue.getSelfURL(), new IsEqual<String>(JSONResources.BLANK_ISSUE1_SELF)
}

View File

@ -3,6 +3,7 @@ package net.rcarz.jiraclient.agile
import net.rcarz.jiraclient.JiraException
import net.rcarz.jiraclient.RestClient
import net.rcarz.jiraclient.RestException
import net.sf.json.JSONObject
import net.sf.json.JSONSerializer
import org.hamcrest.core.IsEqual
import org.hamcrest.core.IsNot
@ -74,18 +75,56 @@ class BoardTest extends AbstractResourceTest {
@Test
void "Given a valid Board, when calling getSprints(), then receive a list of Sprints."() {
RestClient mockRestClient = "given a REST Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "board/${JSONResources.BOARD_ID}"))
.thenReturn(JSONSerializer.toJSON(JSONResources.BOARD))
Board mockBoard = new Board(mockRestClient, JSONSerializer.toJSON(JSONResources.BOARD) as JSONObject)
when(mockRestClient.get(AgileResource.RESOURCE_URI + "board/${JSONResources.BOARD_ID}/sprint"))
.thenReturn(JSONSerializer.toJSON(JSONResources.LIST_OF_SPRINTS))
Board board = Board.get(mockRestClient, JSONResources.BOARD_ID);
"Assert equals to Board ${JSONResources.BOARD_ID}"(board)
List<Sprint> sprints = board.getSprints();
List<Sprint> sprints = mockBoard.getSprints();
assertThat sprints, new IsNot<>(new IsNull())
assertThat sprints.size(), new IsEqual<Integer>(2)
"Assert equals to Sprint ${JSONResources.SPRINT_ID}"(sprints.get(0))
}
@Test
void "Given a valid Board, when calling getEpics(), then receive a list of Epics."() {
RestClient mockRestClient = "given a REST Client"()
Board mockBoard = new Board(mockRestClient, JSONSerializer.toJSON(JSONResources.BOARD) as JSONObject)
when(mockRestClient.get(AgileResource.RESOURCE_URI + "board/${JSONResources.BOARD_ID}/epic"))
.thenReturn(JSONSerializer.toJSON(JSONResources.LIST_OF_EPICS))
List<Epic> epics = mockBoard.getEpics();
assertThat epics, new IsNot<>(new IsNull())
assertThat epics.size(), new IsEqual<Integer>(2)
"Assert equals to Epic ${JSONResources.EPIC_ID}"(epics.get(0))
}
@Test
void "Given a valid Board, when calling getBacklog(), then receive a list of Issues."() {
RestClient mockRestClient = "given a REST Client"()
Board mockBoard = new Board(mockRestClient, JSONSerializer.toJSON(JSONResources.BOARD) as JSONObject)
when(mockRestClient.get(AgileResource.RESOURCE_URI + "board/${JSONResources.BOARD_ID}/backlog"))
.thenReturn(JSONSerializer.toJSON(JSONResources.LIST_OF_ISSUES))
List<Issue> backlog = mockBoard.getBacklog();
assertThat backlog, new IsNot<>(new IsNull())
assertThat backlog.size(), new IsEqual<Integer>(4)
"Assert equals to Issue ${JSONResources.ISSUE_ID}"(backlog.get(0))
}
@Test
void "Given a valid Board, when calling getIssuesWithoutEpic(), then receive a list of Issues."() {
RestClient mockRestClient = "given a REST Client"()
Board mockBoard = new Board(mockRestClient, JSONSerializer.toJSON(JSONResources.BOARD) as JSONObject)
when(mockRestClient.get(AgileResource.RESOURCE_URI + "board/${JSONResources.BOARD_ID}/epic/none/issue"))
.thenReturn(JSONSerializer.toJSON(JSONResources.LIST_OF_ISSUES))
List<Issue> issues = mockBoard.getIssuesWithoutEpic();
assertThat issues, new IsNot<>(new IsNull())
assertThat issues.size(), new IsEqual<Integer>(4)
"Assert equals to Issue ${JSONResources.ISSUE_ID}"(issues.get(0))
}
}

View File

@ -3,11 +3,16 @@ package net.rcarz.jiraclient.agile
import net.rcarz.jiraclient.JiraException
import net.rcarz.jiraclient.RestClient
import net.rcarz.jiraclient.RestException
import net.sf.json.JSONObject
import net.sf.json.JSONSerializer
import org.hamcrest.core.IsEqual
import org.hamcrest.core.IsNot
import org.hamcrest.core.IsNull
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import static org.junit.Assert.assertThat
import static org.mockito.Mockito.when
/**
@ -41,4 +46,64 @@ class EpicTest extends AbstractResourceTest {
Epic.get(mockRestClient, 666);
}
@Test
void "Given an epic without the issue cache, when calling asIssue(false), then call the REST Api."() {
RestClient mockRestClient = "given a REST Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "issue/" + JSONResources.EPIC_ID))
.thenReturn(JSONSerializer.toJSON(JSONResources.ISSUE))
Epic mockEpic = new Epic(mockRestClient, JSONSerializer.toJSON(JSONResources.EPIC) as JSONObject)
assertThat mockEpic.issue, new IsNull()
Issue issue = mockEpic.asIssue(false)
"Assert equals to Issue ${JSONResources.ISSUE_ID}"(issue)
assertThat mockEpic.issue, new IsNot<>(new IsNull())
}
@Test
void "Given an epic with the issue cache, when calling asIssue(false), then use the cache version."() {
RestClient mockRestClient = "given a REST Client"()
Epic mockEpic = new Epic(mockRestClient, JSONSerializer.toJSON(JSONResources.EPIC) as JSONObject)
Issue mockIssue = new Issue(mockRestClient, JSONSerializer.toJSON(JSONResources.ISSUE) as JSONObject)
mockEpic.issue = mockIssue
assertThat mockEpic.issue, new IsNot<>(new IsNull())
Issue issue = mockEpic.asIssue(false)
"Assert equals to Issue ${JSONResources.ISSUE_ID}"(issue)
assertThat mockEpic.issue, new IsNot<>(new IsNull())
assert mockEpic.issue == mockIssue
}
@Test
void "Given an epic with the issue cache, when calling asIssue(true), then call the REST Api."() {
RestClient mockRestClient = "given a REST Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "issue/" + JSONResources.EPIC_ID))
.thenReturn(JSONSerializer.toJSON(JSONResources.ISSUE))
Epic mockEpic = new Epic(mockRestClient, JSONSerializer.toJSON(JSONResources.EPIC) as JSONObject)
Issue mockIssue = new Issue(mockRestClient, JSONSerializer.toJSON(JSONResources.ISSUE) as JSONObject)
mockEpic.issue = mockIssue
assertThat mockEpic.issue, new IsNot<>(new IsNull())
Issue issue = mockEpic.asIssue(true)
"Assert equals to Issue ${JSONResources.ISSUE_ID}"(issue)
assertThat mockEpic.issue, new IsNot<>(new IsNull())
assert mockEpic.issue != mockIssue
}
@Test
void "Given a valid Epic, when calling getIssues(), then receive a list of Issues."() {
RestClient mockRestClient = "given a REST Client"()
Epic mockEpic = new Epic(mockRestClient, JSONSerializer.toJSON(JSONResources.EPIC) as JSONObject)
when(mockRestClient.get(AgileResource.RESOURCE_URI + "epic/${JSONResources.EPIC_ID}/issue"))
.thenReturn(JSONSerializer.toJSON(JSONResources.LIST_OF_ISSUES))
List<Issue> issues = mockEpic.getIssues();
assertThat issues, new IsNot<>(new IsNull())
assertThat issues.size(), new IsEqual<Integer>(4)
"Assert equals to Issue ${JSONResources.ISSUE_ID}"(issues.get(0))
}
}

View File

@ -64,4 +64,15 @@ class IssueTest extends AbstractResourceTest {
Issue.get(mockRestClient, "HSP-2");
}
@Test
void "Given an issue empty, when calling Issue.get(id), then deserialize properly."() {
RestClient mockRestClient = "given a REST Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "issue/" + JSONResources.BLANK_ISSUE1_ID))
.thenReturn(JSONSerializer.toJSON(JSONResources.BLANK_ISSUE1))
Issue issue = Issue.get(mockRestClient, JSONResources.BLANK_ISSUE1_ID);
"Assert equals to Issue ${JSONResources.BLANK_ISSUE1_ID}"(issue)
}
}

View File

@ -85,40 +85,35 @@ interface JSONResources {
},
"done": ${EPIC_DONE}
}"""
String LIST_OF_EPICS = """{
"maxResults": 2,
"startAt": 1,
"total": 5,
"isLast": false,
"values": [
${EPIC},
{
"id": 37,
"self": "http://www.example.com/jira/rest/agile/1.0/epic/13",
"name": "epic 2",
"summary": "epic 2 summary",
"color": {
"key": "color_2"
},
"done": false
}
]
}"""
long ISSUE_ID = 10001L
String ISSUE_SELF = "http://www.example.com/jira/rest/agile/1.0/board/92/issue/10001"
String ISSUE_KEY = "HSP-1"
String ISSUE = """{
"expand": "",
"id": "${ISSUE_ID}",
"self": "${ISSUE_SELF}",
"key": "${ISSUE_KEY}",
"fields": {
"flagged": true,
"sprint": {
"id": ${SPRINT_ID},
"self": "http://www.example.com/jira/rest/agile/1.0/sprint/${SPRINT_ID}",
"state": "future",
"name": "sprint 2"
},
"closedSprints": [
{
"id": 23,
"self": "http://www.example.com/jira/rest/agile/1.0/sprint/23",
"state": "closed",
"name": "sprint 1",
"startDate": "2015-04-11T15:22:00.000+10:00",
"endDate": "2015-04-20T01:22:00.000+10:00",
"completeDate": "2015-04-20T11:04:00.000+10:00"
}
],
"description": "example bug report",
"project": {
"self": "http://www.example.com/jira/rest/api/2/project/EX",
"id": "10000",
"key": "EX",
"name": "Example",
long PROJECT_ID = 10000L
String PROJECT_KEY = "EX"
String PROJECT_NAME = "Example"
String PROJECT_SELF = "http://www.example.com/jira/rest/api/2/project/${PROJECT_KEY}"
String PROJECT = """{
"self": "${PROJECT_SELF}",
"id": "${PROJECT_ID}",
"key": "${PROJECT_KEY}",
"name": "${PROJECT_NAME}",
"avatarUrls": {
"48x48": "http://www.example.com/jira/secure/projectavatar?size=large&pid=10000",
"24x24": "http://www.example.com/jira/secure/projectavatar?size=small&pid=10000",
@ -131,57 +126,41 @@ interface JSONResources {
"name": "FIRST",
"description": "First Project Category"
}
},
"comment": [
{
"self": "http://www.example.com/jira/rest/api/2/issue/10010/comment/10000",
"id": "10000",
"author": {
"self": "http://www.example.com/jira/rest/api/2/user?username=fred",
"name": "fred",
"displayName": "Fred F. User",
"active": false
},
"body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eget venenatis elit. Duis eu justo eget augue iaculis fermentum. Sed semper quam laoreet nisi egestas at posuere augue semper.",
"updateAuthor": {
"self": "http://www.example.com/jira/rest/api/2/user?username=fred",
"name": "fred",
"displayName": "Fred F. User",
"active": false
},
"created": "2016-03-21T15:26:17.875+0100",
"updated": "2016-03-21T15:26:17.878+0100",
"visibility": {
"type": "role",
"value": "Administrators"
}
}
],
"epic": {
"id": 37,
"self": "http://www.example.com/jira/rest/agile/1.0/epic/23",
"name": "epic 1",
"summary": "epic 1 summary",
"color": {
"key": "color_4"
},
"done": true
},
"worklog": [
{
"self": "http://www.example.com/jira/rest/api/2/issue/10010/worklog/10000",
"author": {
"self": "http://www.example.com/jira/rest/api/2/user?username=fred",
"name": "fred",
"displayName": "Fred F. User",
"active": false
},
"updateAuthor": {
"self": "http://www.example.com/jira/rest/api/2/user?username=fred",
"name": "fred",
"displayName": "Fred F. User",
"active": false
},
}"""
String USER_NAME = "Example"
String USER_SELF = "https://www.example.com/rest/api/2/user?username=${USER_NAME}"
String USER = """{
"self" : "${USER_SELF}",
"name" : "${USER_NAME}",
"key" : "pldupont",
"emailAddress" : "pldupont@example.com",
"avatarUrls" : {
"48x48" : "https://www.example.com/secure/useravatar?ownerId=pldupont&avatarId=11828",
"24x24" : "https://www.example.com/secure/useravatar?size=small&ownerId=pldupont&avatarId=11828",
"16x16" : "https://www.example.com/secure/useravatar?size=xsmall&ownerId=pldupont&avatarId=11828",
"32x32" : "https://www.example.com/secure/useravatar?size=medium&ownerId=pldupont&avatarId=11828"
},
"displayName" : "Pierre-Luc Dupont",
"active" : true,
"timeZone" : "America/New_York"
}"""
String ISSUE_TIMETRACKING = """{
"originalEstimate": "10m",
"remainingEstimate": "3m",
"timeSpent": "6m",
"originalEstimateSeconds": 600,
"remainingEstimateSeconds": 200,
"timeSpentSeconds": 400
}"""
long ISSUE_WORKLOG_ID = 100028L
String ISSUE_WORKLOG_SELF = "http://www.example.com/jira/rest/api/2/issue/10010/worklog${ISSUE_WORKLOG_ID}"
String ISSUE_WORKLOG = """{
"self": "${ISSUE_WORKLOG_SELF}",
"author": ${USER},
"updateAuthor": ${USER},
"comment": "I did some work here.",
"updated": "2016-03-21T15:26:17.882+0100",
"visibility": {
@ -191,19 +170,290 @@ interface JSONResources {
"started": "2016-03-21T15:26:17.881+0100",
"timeSpent": "3h 20m",
"timeSpentSeconds": 12000,
"id": "100028",
"id": "${ISSUE_WORKLOG_ID}",
"issueId": "10002"
}
],
}"""
long ISSUE_COMMENT_ID = 9999L
String ISSUE_COMMENT_SELF = "http://www.example.com/jira/rest/api/2/issue/10010/comment/${ISSUE_COMMENT_ID}"
String ISSUE_COMMENT = """{
"self": "${ISSUE_COMMENT_SELF}",
"id": "9999",
"author": ${USER},
"body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eget venenatis elit. Duis eu justo eget augue iaculis fermentum. Sed semper quam laoreet nisi egestas at posuere augue semper.",
"updateAuthor": ${USER},
"created": "2016-03-21T15:26:17.875+0100",
"updated": "2016-03-21T15:26:17.878+0100",
"visibility": {
"type": "role",
"value": "Administrators"
}
}"""
long ISSUE_TYPE_ID = 1L
String ISSUE_TYPE_NAME = "Bug"
String ISSUE_TYPE_SELF = "https://jira.acquisio.com/rest/api/2/issuetype/${ISSUE_TYPE_ID}"
String ISSUE_TYPE = """{
"self" : "${ISSUE_TYPE_SELF}",
"id" : "${ISSUE_TYPE_ID}",
"description" : "A problem which impairs or prevents the functions of the product.",
"iconUrl" : "https://www.example.com/images/icons/issuetypes/bug.png",
"name" : "${ISSUE_TYPE_NAME}",
"subtask" : false
}"""
long ISSUE_RESOLUTION_ID = 6L
String ISSUE_RESOLUTION_NAME = "Not a bug"
String ISSUE_RESOLUTION_SELF = "https://jira.acquisio.com/rest/api/2/resolution/${ISSUE_RESOLUTION_ID}"
String ISSUE_RESOLUTION = """{
"self" : "${ISSUE_RESOLUTION_SELF}",
"id" : "${ISSUE_RESOLUTION_ID}",
"description" : "The problem is not a problem",
"name" : "${ISSUE_RESOLUTION_NAME}"
}"""
long ISSUE_STATUS_ID = 6L
String ISSUE_STATUS_NAME = "Closed"
String ISSUE_STATUS_SELF = "https://www.example.com/rest/api/2/status/${ISSUE_STATUS_ID}"
String ISSUE_STATUS = """{
"self" : "${ISSUE_STATUS_SELF}",
"description" : "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.",
"iconUrl" : "https://www.example.com/images/icons/statuses/closed.png",
"name" : "${ISSUE_STATUS_NAME}",
"id" : "${ISSUE_STATUS_ID}",
"statusCategory" : {
"self" : "https://www.example.com/rest/api/2/statuscategory/3",
"id" : 3,
"key" : "done",
"colorName" : "green",
"name" : "Done"
}
}"""
long ISSUE_PRIORITY_ID = 2L
String ISSUE_PRIORITY_NAME = "Critical"
String ISSUE_PRIORITY_SELF = "https://www.example.com/rest/api/2/priority/${ISSUE_PRIORITY_ID}"
String ISSUE_PRIORITY = """{
"self" : "${ISSUE_PRIORITY_SELF}",
"iconUrl" : "https://www.example.com/images/icons/priorities/critical.png",
"name" : "${ISSUE_PRIORITY_NAME}",
"id" : "${ISSUE_PRIORITY_ID}"
}"""
long ISSUE_ID = 10001L
String ISSUE_SELF = "http://www.example.com/jira/rest/agile/1.0/board/92/issue/10001"
String ISSUE_KEY = "HSP-1"
boolean ISSUE_FLAGGED = true
String ISSUE_DESCRIPTION = "example bug report"
String ISSUE_ENVIRONMENT = "PROD"
String ISSUE_CREATED_STR = "2016-05-11T10:58:01.000-0400"
Date ISSUE_CREATED = Field.getDateTime(ISSUE_CREATED_STR)
String ISSUE_UPDATED_STR = "2016-05-30T14:20:29.000-0400"
Date ISSUE_UPDATED = Field.getDateTime(ISSUE_UPDATED_STR)
String ISSUE = """{
"expand": "",
"id": "${ISSUE_ID}",
"self": "${ISSUE_SELF}",
"key": "${ISSUE_KEY}",
"fields": {
"flagged": ${ISSUE_FLAGGED},
"sprint": ${SPRINT},
"closedSprint": {
"closedSprints": [
{
"id": 21,
"self": "http://www.example.com/jira/rest/agile/1.0/sprint/21",
"state": "closed",
"name": "sprint 1",
"startDate": "2015-04-11T15:22:00.000+10:00",
"endDate": "2015-04-20T01:22:00.000+10:00",
"completeDate": "2015-04-20T11:04:00.000+10:00"
},
{
"id": 22,
"self": "http://www.example.com/jira/rest/agile/1.0/sprint/22",
"state": "closed",
"name": "sprint 1",
"startDate": "2015-04-11T15:22:00.000+10:00",
"endDate": "2015-04-20T01:22:00.000+10:00",
"completeDate": "2015-04-20T11:04:00.000+10:00"
},
{
"id": 23,
"self": "http://www.example.com/jira/rest/agile/1.0/sprint/23",
"state": "closed",
"name": "sprint 1",
"startDate": "2015-04-11T15:22:00.000+10:00",
"endDate": "2015-04-20T01:22:00.000+10:00",
"completeDate": "2015-04-20T11:04:00.000+10:00"
}
]
},
"description": "${ISSUE_DESCRIPTION}",
"project": ${PROJECT},
"comment": {
"comments" : [
${ISSUE_COMMENT}
]
},
"epic": ${EPIC},
"worklog": {
"worklogs": [
${ISSUE_WORKLOG}
]
},
"updated": 1,
"timetracking": {
"originalEstimate": "10m",
"remainingEstimate": "3m",
"timeSpent": "6m",
"originalEstimateSeconds": 600,
"remainingEstimateSeconds": 200,
"timeSpentSeconds": 400
}
"timetracking": ${ISSUE_TIMETRACKING},
"environment": "${ISSUE_ENVIRONMENT}",
"issuetype" : ${ISSUE_TYPE},
"resolution" : ${ISSUE_RESOLUTION},
"assignee" : ${USER},
"creator" : ${USER},
"reporter" : ${USER},
"created" : "${ISSUE_CREATED_STR}",
"updated" : "${ISSUE_UPDATED_STR}",
"status" : ${ISSUE_STATUS},
"priority" : ${ISSUE_PRIORITY},
}
}"""
long BLANK_ISSUE1_ID = 10010
String BLANK_ISSUE1_SELF = "http://www.example.com/jira/rest/agile/1.0/board/92/issue/${BLANK_ISSUE1_ID}"
String BLANK_ISSUE1_KEY = "HSP-1"
String BLANK_ISSUE1 = """{
"expand": "",
"id": "${BLANK_ISSUE1_ID}",
"self": "${BLANK_ISSUE1_SELF}",
"key": "${BLANK_ISSUE1_KEY}",
}"""
long BLANK_ISSUE2_ID = 10011
String BLANK_ISSUE2_SELF = "http://www.example.com/jira/rest/agile/1.0/board/92/issue/${BLANK_ISSUE2_ID}"
String BLANK_ISSUE2_KEY = "HSP-1"
String BLANK_ISSUE2 = """{
"expand": "",
"id": "${BLANK_ISSUE2_ID}",
"self": "${BLANK_ISSUE2_SELF}",
"key": "${BLANK_ISSUE2_KEY}",
"fields": {
"flagged": false,
}
}"""
String LIST_OF_ISSUES = """{
"expand": "names,schema",
"startAt": 0,
"maxResults": 50,
"total": 1,
"issues": [
${ISSUE},
${BLANK_ISSUE1},
${BLANK_ISSUE2},
{
"expand": "",
"id": "10005",
"self": "http://www.example.com/jira/rest/agile/1.0/board/92/issue/10005",
"key": "HSP-9",
"fields": {
"flagged": true,
"sprint": ${SPRINT},
"closedSprint" : {
"closedSprints": [
{
"id": 37,
"self": "http://www.example.com/jira/rest/agile/1.0/sprint/23",
"state": "closed",
"name": "sprint 1",
"startDate": "2015-04-11T15:22:00.000+10:00",
"endDate": "2015-04-20T01:22:00.000+10:00",
"completeDate": "2015-04-20T11:04:00.000+10:00"
}
]
},
"description": "example bug report",
"project": {
"self": "http://www.example.com/jira/rest/api/2/project/EX",
"id": "10000",
"key": "EX",
"name": "Example",
"avatarUrls": {
"48x48": "http://www.example.com/jira/secure/projectavatar?size=large&pid=10000",
"24x24": "http://www.example.com/jira/secure/projectavatar?size=small&pid=10000",
"16x16": "http://www.example.com/jira/secure/projectavatar?size=xsmall&pid=10000",
"32x32": "http://www.example.com/jira/secure/projectavatar?size=medium&pid=10000"
},
"projectCategory": {
"self": "http://www.example.com/jira/rest/api/2/projectCategory/10000",
"id": "10000",
"name": "FIRST",
"description": "First Project Category"
}
},
"comment": {
"comments": [
{
"self": "http://www.example.com/jira/rest/api/2/issue/10010/comment/10000",
"id": "10000",
"author": {
"self": "http://www.example.com/jira/rest/api/2/user?username=fred",
"name": "fred",
"displayName": "Fred F. User",
"active": false
},
"body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eget venenatis elit. Duis eu justo eget augue iaculis fermentum. Sed semper quam laoreet nisi egestas at posuere augue semper.",
"updateAuthor": {
"self": "http://www.example.com/jira/rest/api/2/user?username=fred",
"name": "fred",
"displayName": "Fred F. User",
"active": false
},
"created": "2016-03-21T15:26:17.875+0100",
"updated": "2016-03-21T15:26:17.878+0100",
"visibility": {
"type": "role",
"value": "Administrators"
}
}
]
},
"epic": ${EPIC},
"worklog": {
"worklogs": [
{
"self": "http://www.example.com/jira/rest/api/2/issue/10010/worklog/10000",
"author": {
"self": "http://www.example.com/jira/rest/api/2/user?username=fred",
"name": "fred",
"displayName": "Fred F. User",
"active": false
},
"updateAuthor": {
"self": "http://www.example.com/jira/rest/api/2/user?username=fred",
"name": "fred",
"displayName": "Fred F. User",
"active": false
},
"comment": "I did some work here.",
"updated": "2016-03-21T15:26:17.882+0100",
"visibility": {
"type": "group",
"value": "jira-developers"
},
"started": "2016-03-21T15:26:17.881+0100",
"timeSpent": "3h 20m",
"timeSpentSeconds": 12000,
"id": "100028",
"issueId": "10002"
}
]
},
"updated": 1,
"timetracking": {
"originalEstimate": "10m",
"remainingEstimate": "3m",
"timeSpent": "6m",
"originalEstimateSeconds": 600,
"remainingEstimateSeconds": 200,
"timeSpentSeconds": 400
}
}
}
]
}"""
}

View File

@ -3,6 +3,7 @@ package net.rcarz.jiraclient.agile
import net.rcarz.jiraclient.JiraException
import net.rcarz.jiraclient.RestClient
import net.rcarz.jiraclient.RestException
import net.sf.json.JSONObject
import net.sf.json.JSONSerializer
import org.hamcrest.core.IsEqual
import org.hamcrest.core.IsNot
@ -70,4 +71,18 @@ class SprintTest extends AbstractResourceTest {
Sprint.get(mockRestClient, 666);
}
@Test
void "Given a valid Sprint, when calling getIssues(), then receive a list of Issues."() {
RestClient mockRestClient = "given a REST Client"()
Sprint mockSprint = new Sprint(mockRestClient, JSONSerializer.toJSON(JSONResources.SPRINT) as JSONObject)
when(mockRestClient.get(AgileResource.RESOURCE_URI + "sprint/${JSONResources.SPRINT_ID}/issue"))
.thenReturn(JSONSerializer.toJSON(JSONResources.LIST_OF_ISSUES))
List<Issue> issues = mockSprint.getIssues();
assertThat issues, new IsNot<>(new IsNull())
assertThat issues.size(), new IsEqual<Integer>(4)
"Assert equals to Issue ${JSONResources.ISSUE_ID}"(issues.get(0))
}
}