1
0
Fork 0

Merge pull request #1 from pldupont/agile-API

Agile api - completed the read-only mode
master
Pierre-Luc Dupont 2016-06-01 22:46:36 -04:00
commit d0db6b0bf8
29 changed files with 3301 additions and 94 deletions

5
.gitignore vendored
View File

@ -154,3 +154,8 @@ nb-configuration.xml
Session.vim
.netrwhist
*~
### Acquisio related test ###
*AcquisioTest.java
*AcquisioTest.groovy
credentials.groovy

View File

@ -3,3 +3,4 @@ Kyle Chaplin <chaplinkyle@gmail.com> @chaplinkyle
Alesandro Lang <info@alesandro-lang.com> @alesandroLang
Javier Molina <javinovich@gmail.com> @javinovich
Joseph McCarthy <luckymikuhatsune@gmail.com>
Pierre-Luc Dupont <pldupont@gmail.com> @pldupont

View File

@ -273,4 +273,68 @@ public class Example {
System.err.println(ex.getCause().getMessage());
}
}
}
```
## Agile API ##
https://docs.atlassian.com/jira-software/REST/cloud/
### Agile supported calls ###
| 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} |
### Agile Example ###
To see more examples, look at [AgileClientDemoTest](test/groovy/AgileClientDemoTest.groovy)
```java
import java.util.List;
import net.rcarz.jiraclient.BasicCredentials;
import net.rcarz.jiraclient.Issue;
import net.rcarz.jiraclient.JiraClient;
import net.rcarz.jiraclient.JiraException;
import net.rcarz.jiraclient.agile.Board;
import net.rcarz.jiraclient.agile.AgileClient;
public class Example {
public static void main(String[] args) {
BasicCredentials creds = new BasicCredentials("batman", "pow! pow!");
JiraClient jira = new JiraClient("https://jira.example.com/jira", creds);
AgileClient agileClient = new AgileClient(jira);
try {
/* Retrieve all Boards */
List<Board> allBoards = agileClient.getBoards();
} catch (JiraException ex) {
System.err.println(ex.getMessage());
if (ex.getCause() != null) {
System.err.println(ex.getCause().getMessage());
}
}
}
}
```

View File

@ -85,6 +85,12 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.4.6</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -19,107 +19,24 @@
package net.rcarz.jiraclient;
import java.lang.Iterable;
import java.lang.UnsupportedOperationException;
import net.sf.json.JSONArray;
import net.sf.json.JSONNull;
import net.sf.json.JSONObject;
import java.sql.Timestamp;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JSONNull;
import java.util.*;
/**
* Utility functions for translating between JSON and fields.
*/
public final class Field {
/**
* Field metadata structure.
*/
public static final class Meta {
public boolean required;
public String type;
public String items;
public String name;
public String system;
public String custom;
public int customId;
}
/**
* Field update operation.
*/
public static final class Operation {
public String name;
public Object value;
/**
* Initialises a new update operation.
*
* @param name Operation name
* @param value Field value
*/
public Operation(String name, Object value) {
this.name = name;
this.value = value;
}
}
/**
* Allowed value types.
*/
public enum ValueType {
KEY("key"), NAME("name"), ID_NUMBER("id"), VALUE("value");
private String typeName;
private ValueType(String typeName) {
this.typeName = typeName;
}
@Override
public String toString() {
return typeName;
}
};
/**
* Value and value type pair.
*/
public static final class ValueTuple {
public final String type;
public final Object value;
/**
* Initialises the value tuple.
*
* @param type
* @param value
*/
public ValueTuple(String type, Object value) {
this.type = type;
this.value = (value != null ? value : JSONNull.getInstance());
}
/**
* Initialises the value tuple.
*
* @param type
* @param value
*/
public ValueTuple(ValueType type, Object value) {
this(type.toString(), value);
}
}
public static final String ASSIGNEE = "assignee";
public static final String ATTACHMENT = "attachment";
public static final String CHANGE_LOG = "changelog";
;
public static final String CHANGE_LOG_ENTRIES = "histories";
public static final String CHANGE_LOG_ITEMS = "items";
public static final String COMMENT = "comment";
@ -149,10 +66,8 @@ public final class Field {
public static final String CREATED_DATE = "created";
public static final String UPDATED_DATE = "updated";
public static final String TRANSITION_TO_STATUS = "to";
public static final String DATE_FORMAT = "yyyy-MM-dd";
public static final String DATETIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
private Field() { }
/**
@ -204,7 +119,7 @@ public final class Field {
return results;
}
/**
* Gets a list of remote links from the given object.
*
@ -290,6 +205,24 @@ public final class Field {
return result;
}
/**
* Gets a long from the given object.
*
* @param i a Long or an Integer instance
*
* @return a long primitive or 0 if i isn't a Long or an Integer instance
*/
public static long getLong(Object i) {
long result = 0;
if (i instanceof Long)
result = ((Long) i).longValue();
if (i instanceof Integer)
result = ((Integer) i).intValue();
return result;
}
/**
* Gets a generic map from the given object.
*
@ -553,7 +486,7 @@ public final class Field {
} else if (type.equals("string") && custom != null
&& (custom.equals("com.atlassian.jira.plugin.system.customfieldtypes:multicheckboxes") ||
custom.equals("com.atlassian.jira.plugin.system.customfieldtypes:multiselect"))) {
realResult = new JSONObject();
((JSONObject)realResult).put(ValueType.VALUE.toString(), realValue.toString());
} else if (type.equals("string"))
@ -658,7 +591,7 @@ public final class Field {
else if (value instanceof TimeTracking)
return ((TimeTracking) value).toJsonObject();
} else if (m.type.equals("number")) {
if(!(value instanceof java.lang.Integer) && !(value instanceof java.lang.Double) && !(value
if (!(value instanceof java.lang.Integer) && !(value instanceof java.lang.Double) && !(value
instanceof java.lang.Float) && !(value instanceof java.lang.Long) )
{
throw new JiraException("Field '" + name + "' expects a Numeric value");
@ -722,5 +655,83 @@ public final class Field {
public static ValueTuple valueById(String id) {
return new ValueTuple(ValueType.ID_NUMBER, id);
}
/**
* Allowed value types.
*/
public enum ValueType {
KEY("key"), NAME("name"), ID_NUMBER("id"), VALUE("value");
private String typeName;
private ValueType(String typeName) {
this.typeName = typeName;
}
@Override
public String toString() {
return typeName;
}
}
/**
* Field metadata structure.
*/
public static final class Meta {
public boolean required;
public String type;
public String items;
public String name;
public String system;
public String custom;
public int customId;
}
/**
* Field update operation.
*/
public static final class Operation {
public String name;
public Object value;
/**
* Initialises a new update operation.
*
* @param name Operation name
* @param value Field value
*/
public Operation(String name, Object value) {
this.name = name;
this.value = value;
}
}
/**
* Value and value type pair.
*/
public static final class ValueTuple {
public final String type;
public final Object value;
/**
* Initialises the value tuple.
*
* @param type
* @param value
*/
public ValueTuple(String type, Object value) {
this.type = type;
this.value = (value != null ? value : JSONNull.getInstance());
}
/**
* Initialises the value tuple.
*
* @param type
* @param value
*/
public ValueTuple(ValueType type, Object value) {
this(type.toString(), value);
}
}
}

View File

@ -0,0 +1,116 @@
/**
* 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.JiraClient;
import net.rcarz.jiraclient.JiraException;
import net.rcarz.jiraclient.RestClient;
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 {
private RestClient restclient = null;
/**
* Creates an Agile client.
*
* @param jira JIRA client
*/
public AgileClient(JiraClient jira) {
restclient = jira.getRestClient();
}
/**
* Retrieves the board with the given ID.
*
* @param id Board ID
* @return a Board instance
* @throws JiraException when something goes wrong
*/
public Board getBoard(long id) throws JiraException {
return Board.get(restclient, id);
}
/**
* Retrieves all boards visible to the session user.
*
* @return a list of boards
* @throws JiraException when something goes wrong
*/
public List<Board> getBoards() throws JiraException {
return Board.getAll(restclient);
}
/**
* Retrieves the sprint with the given ID.
*
* @param id Sprint ID
* @return a Sprint instance
* @throws JiraException when something goes wrong
*/
public Sprint getSprint(long id) throws JiraException {
return Sprint.get(restclient, id);
}
/**
* Retrieves the issue with the given ID.
*
* @param id Issue ID
* @return an Issue instance
* @throws JiraException when something goes wrong
*/
public Issue getIssue(long id) throws JiraException {
return Issue.get(restclient, id);
}
/**
* Retrieves the issue with the given Key.
*
* @param key Issue Key
* @return an Issue instance
* @throws JiraException when something goes wrong
*/
public Issue getIssue(String key) throws JiraException {
return Issue.get(restclient, key);
}
/**
* Retrieves the epic with the given ID.
*
* @param id Epic ID
* @return an Epic instance
* @throws JiraException when something goes wrong
*/
public Epic getEpic(long id) throws JiraException {
return Epic.get(restclient, id);
}
public RestClient getRestclient() {
return restclient;
}
}

View File

@ -0,0 +1,318 @@
/**
* 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.JSON;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.math.NumberUtils;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
/**
* A base class for Agile resources.
*
* @author pldupont
* @see "https://docs.atlassian.com/jira-software/REST/cloud/"
*/
public abstract class AgileResource {
public static final String ATTR_ID = "id";
public static final String ATTR_NAME = "name";
public static final String ATTR_SELF = "self";
public static final String RESOURCE_URI = "/rest/agile/1.0/";
private RestClient restclient = null;
private long id = 0;
private String name;
private String self;
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) throws JiraException {
this.restclient = restclient;
if (json != null) {
deserialize(json);
}
}
/**
* Gets an Agile resource from the given object.
*
* @param type Resource data type
* @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
*/
protected static <T extends AgileResource> T getResource(
Class<T> type, Object r, RestClient restclient) throws JiraException {
if (!(r instanceof JSONObject)) {
throw new JiraException("JSON payload is malformed");
}
T result = null;
if (!((JSONObject) r).isNullObject()) {
try {
Constructor<T> constructor = type.getDeclaredConstructor(RestClient.class, JSONObject.class);
result = constructor.newInstance(restclient, r);
} catch (Exception e) {
throw new JiraException("Failed to deserialize object.", e);
}
}
return result;
}
/**
* Gets a list of GreenHopper resources from the given object.
*
* @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
*/
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(listName) || !(jo.get(listName) instanceof JSONArray)) {
throw new JiraException("No array found for name '" + listName + "'");
}
List<T> results = new ArrayList<T>();
for (Object v : (JSONArray) jo.get(listName)) {
T item = getResource(type, v, restclient);
if (item != null) {
results.add(item);
}
}
return results;
}
/**
* 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 {
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 {
result = restclient.get(url);
} catch (Exception ex) {
throw new JiraException("Failed to retrieve a list of " + type.getSimpleName() + " : " + url, ex);
}
return getResourceArray(
type,
result,
restclient,
listName
);
}
/**
* Retrieves all boards visible to the session user.
*
* @param restclient REST client instance
* @return a list of boards
* @throws JiraException when the retrieval fails
*/
static <T extends AgileResource> T get(RestClient restclient, Class<T> type, String url) throws JiraException {
JSON result;
try {
result = restclient.get(url);
} catch (Exception ex) {
throw new JiraException("Failed to retrieve " + type.getSimpleName() + " : " + url, ex);
}
return getResource(
type,
result,
restclient
);
}
/**
* 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) && !subJson.get(resourceName).equals("null")) {
result = getResource(type, subJson.get(resourceName), getRestclient());
}
return result;
}
/**
* @return Internal JIRA ID.
*/
public long getId() {
return id;
}
/**
* @return The resource name.
*/
public String getName() {
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.
*/
public String getSelfURL() {
return self;
}
/**
* @return The REST client used to access the current resource.
*/
protected RestClient getRestclient() {
return restclient;
}
/**
* Retrieve the specified attribute as a generic object.
*
* @param name The name of the attribute to retrieve.
* @return The value of the attribute.
*/
public Object getAttribute(String name) {
return attributes.get(name);
}
/**
* Deserialize the json to extract standard attributes and keep a reference of
* other attributes.
*
* @param json The JSON object to read.
*/
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.getLong(o);
} else if (o instanceof String && NumberUtils.isDigits((String) o)) {
return NumberUtils.toLong((String) o, 0L);
} else {
return 0L;
}
}
@Override
public String toString() {
return String.format("%s{id=%s, name='%s'}", getClass().getSimpleName(), id, name);
}
}

View File

@ -0,0 +1,116 @@
/**
* 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.List;
/**
* Represents an Agile Board.
*
* @author pldupont
*/
public class Board extends AgileResource {
private String type;
/**
* Creates a Board from a JSON payload.
*
* @param restclient REST client instance
* @param json JSON payload
*/
protected Board(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
/**
* Retrieves the given rapid view.
*
* @param restclient REST client instance
* @param id Internal JIRA ID of the rapid view
* @return a rapid view instance
* @throws JiraException when the retrieval fails
*/
public static Board get(RestClient restclient, long id) throws JiraException {
return AgileResource.get(restclient, Board.class, RESOURCE_URI + "board/" + id);
}
/**
* Retrieves all boards visible to the session user.
*
* @param restclient REST client instance
* @return a list of boards
* @throws JiraException when the retrieval fails
*/
public static List<Board> getAll(RestClient restclient) throws JiraException {
return AgileResource.list(restclient, Board.class, RESOURCE_URI + "board");
}
@Override
protected void deserialize(JSONObject json) throws JiraException {
super.deserialize(json);
type = Field.getString(json.get("type"));
}
/**
* @return The board type.
*/
public String getType() {
return this.type;
}
/**
* @return All sprints related to the current board.
* @throws JiraException when the retrieval fails
*/
public List<Sprint> getSprints() throws JiraException {
return Sprint.getAll(getRestclient(), getId());
}
/**
* @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

@ -0,0 +1,93 @@
/**
* 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;
/**
* Represents an Agile Comment.
*
* @author pldupont
*/
public class Comment extends AgileResource {
private User author;
private String body;
private User updateAuthor;
private Date created;
private Date updated;
/**
* Creates a new Agile resource.
*
* @param restclient REST client instance
* @param json JSON payload
*/
public Comment(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
/**
* Deserialize the json to extract standard attributes and keep a reference of
* other attributes.
*
* @param json The JSON object to read.
*/
@Override
void deserialize(JSONObject json) throws JiraException {
super.deserialize(json);
this.author = getSubResource(User.class, json, "author");
this.body = Field.getString(json.get("body"));
this.updateAuthor = getSubResource(User.class, json, "updateAuthor");
this.created = Field.getDateTime(json.get("created"));
this.updated = Field.getDateTime(json.get("updated"));
}
@Override
public String toString() {
return String.format("%s{id=%s, body='%s'}", getClass().getSimpleName(), getId(), getBody());
}
public User getAuthor() {
return author;
}
public String getBody() {
return body;
}
public User getUpdateAuthor() {
return updateAuthor;
}
public Date getCreated() {
return created;
}
public Date getUpdated() {
return updated;
}
}

View File

@ -0,0 +1,109 @@
/**
* 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.List;
/**
* Represents an Agile Epic.
*
* @author pldupont
*/
public class Epic extends AgileResource {
private Issue issue;
private String key;
private String summary;
private boolean done;
/**
* Creates a new Agile resource.
*
* @param restclient REST client instance
* @param json JSON payload
*/
public Epic(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
/**
* Retrieves the epic matching the ID.
*
* @param restclient REST client instance
* @param id Internal JIRA ID of the epic
* @return an epic instance
* @throws JiraException when the retrieval fails
*/
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");
}
/**
* Deserialize the json to extract standard attributes and keep a reference of
* other attributes.
*
* @param json The JSON object to read.
*/
@Override
void deserialize(JSONObject json) throws JiraException {
super.deserialize(json);
this.key = Field.getString(json.get("key"));
this.summary = Field.getString(json.get("summary"));
this.done = Field.getBoolean(json.get("done"));
}
public String getKey() {
return key;
}
public String getSummary() {
return summary;
}
public boolean isDone() {
return done;
}
}

View File

@ -0,0 +1,205 @@
/**
* 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;
/**
* 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) throws JiraException {
super(restclient, json);
}
/**
* Retrieves the issue matching the ID.
*
* @param restclient REST client instance
* @param id Internal JIRA ID of the issue
* @return an issue instance
* @throws JiraException when the retrieval fails
*/
public static Issue get(RestClient restclient, long id) throws JiraException {
return AgileResource.get(restclient, Issue.class, RESOURCE_URI + "issue/" + id);
}
/**
* Retrieves the issue matching the ID.
*
* @param restclient REST client instance
* @param key JIRA key of the issue
* @return an issue instance
* @throws JiraException when the retrieval fails
*/
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,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;
/**
* Represents an Agile IssueType.
*
* @author pldupont
*/
public class IssueType extends AgileResource {
private String description;
private boolean subTask;
/**
* 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);
}
/**
* Deserialize the json to extract standard attributes and keep a reference of
* other attributes.
*
* @param json The JSON object to read.
*/
@Override
void deserialize(JSONObject json) throws JiraException {
super.deserialize(json);
this.description = Field.getString(json.get("description"));
this.subTask = Field.getBoolean(json.get("subtask"));
}
public String getDescription() {
return description;
}
public boolean isSubTask() {
return subTask;
}
}

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

@ -0,0 +1,62 @@
/**
* 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;
/**
* Represents an Agile Project.
*
* @author pldupont
*/
public class Project extends AgileResource {
private String key;
/**
* Creates a new Agile resource.
*
* @param restclient REST client instance
* @param json JSON payload
*/
public Project(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
/**
* Deserialize the json to extract standard attributes and keep a reference of
* other attributes.
*
* @param json The JSON object to read.
*/
@Override
void deserialize(JSONObject json) throws JiraException {
super.deserialize(json);
this.key = Field.getString(json.get("key"));
}
public String getKey() {
return key;
}
}

View File

@ -0,0 +1,62 @@
/**
* 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;
/**
* Represents an Agile Resolution.
*
* @author pldupont
*/
public class Resolution extends AgileResource {
private String description;
/**
* 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);
}
/**
* Deserialize the json to extract standard attributes and keep a reference of
* other attributes.
*
* @param json The JSON object to read.
*/
@Override
void deserialize(JSONObject json) throws JiraException {
super.deserialize(json);
this.description = Field.getString(json.get("description"));
}
public String getDescription() {
return description;
}
}

View File

@ -0,0 +1,115 @@
/**
* 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;
/**
* Represents an Agile Sprint.
*
* @author pldupont
*/
public class Sprint extends AgileResource {
private String state;
private long originBoardId;
private Date startDate;
private Date endDate;
private Date completeDate;
/**
* Creates a rapid view from a JSON payload.
*
* @param restclient REST client instance
* @param json JSON payload
*/
protected Sprint(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
/**
* Retrieve all sprints related to the specified board.
*
* @param restclient REST client instance
* @param sprintId The Internal JIRA sprint ID.
* @return The sprint for the specified ID.
* @throws JiraException when the retrieval fails
*/
public static Sprint get(RestClient restclient, long sprintId) throws JiraException {
return AgileResource.get(restclient, Sprint.class, RESOURCE_URI + "sprint/" + sprintId);
}
/**
* Retrieve all sprints related to the specified board.
*
* @param restclient REST client instance
* @param boardId The Internal JIRA board ID.
* @return The list of sprints associated to the board.
* @throws JiraException when the retrieval fails
*/
public static List<Sprint> getAll(RestClient restclient, long boardId) throws JiraException {
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) throws JiraException {
super.deserialize(json);
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() {
return state;
}
public long getOriginBoardId() {
return originBoardId;
}
public Date getStartDate() {
return startDate;
}
public Date getEndDate() {
return endDate;
}
public Date getCompleteDate() {
return completeDate;
}
}

View File

@ -0,0 +1,62 @@
/**
* 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;
/**
* Represents an Agile Status.
*
* @author pldupont
*/
public class Status extends AgileResource {
private String description;
/**
* 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);
}
/**
* Deserialize the json to extract standard attributes and keep a reference of
* other attributes.
*
* @param json The JSON object to read.
*/
@Override
void deserialize(JSONObject json) throws JiraException {
super.deserialize(json);
this.description = Field.getString(json.get("description"));
}
public String getDescription() {
return description;
}
}

View File

@ -0,0 +1,97 @@
/**
* 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;
/**
* Represents an Agile TimeTracking.
*
* @author pldupont
*/
public class TimeTracking extends AgileResource {
private String originalEstimate;
private String remainingEstimate;
private String timeSpent;
private long originalEstimateSeconds;
private long remainingEstimateSeconds;
private long timeSpentSeconds;
/**
* Creates a new Agile resource.
*
* @param restclient REST client instance
* @param json JSON payload
*/
public TimeTracking(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
/**
* Deserialize the json to extract standard attributes and keep a reference of
* other attributes.
*
* @param json The JSON object to read.
*/
@Override
void deserialize(JSONObject json) throws JiraException {
super.deserialize(json);
this.originalEstimate = Field.getString(json.get("originalEstimate"));
this.remainingEstimate = Field.getString(json.get("remainingEstimate"));
this.timeSpent = Field.getString(json.get("timeSpent"));
this.originalEstimateSeconds = Field.getLong(json.get("originalEstimateSeconds"));
this.remainingEstimateSeconds = Field.getLong(json.get("remainingEstimateSeconds"));
this.timeSpentSeconds = Field.getLong(json.get("timeSpentSeconds"));
}
@Override
public String toString() {
return String.format("%s{original='%s', remaining='%s', timeSpent='%s'}",
getClass().getSimpleName(), getOriginalEstimate(), getRemainingEstimate(), getTimeSpent());
}
public String getOriginalEstimate() {
return originalEstimate;
}
public String getRemainingEstimate() {
return remainingEstimate;
}
public String getTimeSpent() {
return timeSpent;
}
public long getOriginalEstimateSeconds() {
return originalEstimateSeconds;
}
public long getRemainingEstimateSeconds() {
return remainingEstimateSeconds;
}
public long getTimeSpentSeconds() {
return timeSpentSeconds;
}
}

View File

@ -0,0 +1,84 @@
/**
* 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;
/**
* Represents an Agile User.
*
* @author pldupont
*/
public class User extends AgileResource {
private String emailAddress;
private String displayName;
private boolean active;
private String timeZone;
/**
* 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);
}
/**
* Deserialize the json to extract standard attributes and keep a reference of
* other attributes.
*
* @param json The JSON object to read.
*/
@Override
void deserialize(JSONObject json) throws JiraException {
super.deserialize(json);
this.emailAddress = Field.getString(json.get("emailAddress"));
this.displayName = Field.getString(json.get("displayName"));
this.active = Field.getBoolean(json.get("active"));
this.timeZone = Field.getString(json.get("timeZone"));
}
@Override
public String toString() {
return String.format("%s{name='%s', Display Name='%s'}", getClass().getSimpleName(), getName(), getDisplayName());
}
public String getEmailAddress() {
return emailAddress;
}
public String getDisplayName() {
return displayName;
}
public boolean isActive() {
return active;
}
public String getTimeZone() {
return timeZone;
}
}

View File

@ -0,0 +1,110 @@
/**
* 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;
/**
* Represents an Agile Worklog.
*
* @author pldupont
*/
public class Worklog extends AgileResource {
private User author;
private String comment;
private Date created;
private Date updated;
private User updateAuthor;
private Date started;
private String timeSpent;
private long timeSpentSeconds;
/**
* Creates a new Agile resource.
*
* @param restclient REST client instance
* @param json JSON payload
*/
public Worklog(RestClient restclient, JSONObject json) throws JiraException {
super(restclient, json);
}
/**
* Deserialize the json to extract standard attributes and keep a reference of
* other attributes.
*
* @param json The JSON object to read.
*/
@Override
void deserialize(JSONObject json) throws JiraException {
super.deserialize(json);
this.author = getSubResource(User.class, json, "author");
this.comment = Field.getString(json.get("comment"));
this.created = Field.getDateTime(json.get("created"));
this.updated = Field.getDateTime(json.get("updated"));
this.updateAuthor = getSubResource(User.class, json, "updateAuthor");
this.started = Field.getDateTime(json.get("started"));
this.timeSpent = Field.getString(json.get("timeSpent"));
this.timeSpentSeconds = Field.getLong(json.get("timeSpentSeconds"));
}
@Override
public String toString() {
return String.format("%s{id=%s, comment='%s'}", getClass().getSimpleName(), getId(), getComment());
}
public User getAuthor() {
return author;
}
public String getComment() {
return comment;
}
public Date getCreated() {
return created;
}
public Date getUpdated() {
return updated;
}
public User getUpdateAuthor() {
return updateAuthor;
}
public Date getStarted() {
return started;
}
public String getTimeSpent() {
return timeSpent;
}
public long getTimeSpentSeconds() {
return timeSpentSeconds;
}
}

View File

@ -0,0 +1,137 @@
import net.rcarz.jiraclient.BasicCredentials
import net.rcarz.jiraclient.JiraClient
import net.rcarz.jiraclient.agile.*
import org.junit.Ignore
import org.junit.Test
/**
* Demo test, used to show how to use the AgileClient API.
* @author pldupont
*/
class AgileClientDemoTest {
private static final long BOARD_ID = 507L;
private static final long SPRINT_ID = 1165L;
private static final long EPIC_ID = 62133L;
private static final long ISSUE_ID = 63080L;
private static final String ISSUE_KEY = "TEST-1551";
@Test
@Ignore("Demo to use the AgileClient")
public void demoUsingAgileClient() {
// Init Agile client
AgileClient agileClient = new AgileClient(new JiraClient("https://jira.example.com/jira", new BasicCredentials("batman", "pow! pow!")))
demoBoard(agileClient)
demoSprint(agileClient)
demoEpic(agileClient)
demoIssue(agileClient)
}
static void demoSprint(AgileClient agileClient) {
println "********** Sprint demo"
// Retrieve all sprints
List<Sprint> sprints = Sprint.getAll(agileClient.getRestclient(), BOARD_ID)
println sprints
// Retrieve a specific Sprint
Sprint sprint1 = agileClient.getSprint(SPRINT_ID)
println sprint1
Sprint sprint2 = Sprint.get(agileClient.getRestclient(), SPRINT_ID)
println sprint2
println sprint1.toString() == sprint2.toString()
println sprint1.getSelfURL()
// Retrieve issues associated to the sprint
List<Issue> issues = sprint1.getIssues()
println issues
}
static void demoIssue(AgileClient agileClient) {
println "********** Issue demo"
// Retrieve a specific Issue
Issue issue1 = agileClient.getIssue(ISSUE_ID)
println issue1
Issue issue2 = Issue.get(agileClient.getRestclient(), ISSUE_ID)
println issue2
println issue1.toString() == issue2.toString()
Issue issue3 = agileClient.getIssue(ISSUE_KEY)
println issue3
println issue1.toString() == issue3.toString()
println issue1.getSelfURL()
// Retrieve the issue attribute
println issue1.getProject()
println issue1.getEpic()
println issue1.getSprint()
println issue1.getKey();
println issue1.isFlagged();
println issue1.getDescription();
println issue1.getComments();
println issue1.getWorklogs();
println issue1.getTimeTracking();
println issue1.getIssueType();
println issue1.getStatus();
println issue1.getResolution();
println issue1.getCreated();
println issue1.getUpdated();
println issue1.getPriority();
println issue1.getAssignee();
println issue1.getCreator();
println issue1.getReporter();
println issue1.getEnvironment();
}
static void demoEpic(AgileClient agileClient) {
println "********** Epic demo"
// Retrieve a specific Epic
Epic epic1 = agileClient.getEpic(EPIC_ID)
println epic1
Epic epic2 = Epic.get(agileClient.getRestclient(), EPIC_ID)
println epic2
println epic1.toString() == epic2.toString()
println epic1.getSelfURL()
// Retrieve the epic as a normal Issue
Issue issue = epic1.asIssue(true)
println issue
// pldupont: Doesn't work with my version of JIRA, but the doc says otherwise.
// // Retrieve issues associated to the Epic
// List<Issue> issues = epic1.getIssues()
// println issues
}
static void demoBoard(AgileClient agileClient) {
println "********** Board demo"
// Retrieve all board
List<Board> boards = agileClient.getBoards()
println boards
// Retrieve a specific Board
Board board1 = agileClient.getBoard(BOARD_ID)
println board1
Board board2 = Board.get(agileClient.getRestclient(), BOARD_ID)
println board2
println board1.toString() == board2.toString()
println board1.getSelfURL()
// Retrieve sprints associated to the board
List<Sprint> sprints = board1.getSprints()
println sprints
// Retrieve sprints associated to the board
List<Epic> epics = board1.getEpics()
println epics
// Retrieve sprints associated to the board
List<Issue> backlog = board1.getBacklog()
println backlog
// pldupont: Doesn't work with my version of JIRA, but the doc says otherwise.
// // Retrieve sprints associated to the board
// List<Sprint> issuesWithoutEpics = board1.getIssuesWithoutEpic()
// println sprints
}
}

View File

@ -0,0 +1,246 @@
package net.rcarz.jiraclient.agile
import net.rcarz.jiraclient.JiraClient
import net.rcarz.jiraclient.RestClient
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 static org.junit.Assert.assertThat
import static org.mockito.Mockito.mock
import static org.mockito.Mockito.when
/**
* Created on 2016-05-19.
* @author pldupont
*/
class AbstractResourceTest {
AgileClient agileClient;
RestClient mockRestClient;
void "given an Agile Client"() {
mockRestClient = mock RestClient.class
def mockJiraClient = mock JiraClient.class
when(mockJiraClient.getRestClient()).thenReturn(mockRestClient)
agileClient = new AgileClient(mockJiraClient)
}
RestClient "given a REST Client"() {
mockRestClient = mock RestClient.class
return mockRestClient
}
Issue "given an Issue"() {
mockRestClient = mock RestClient.class
return new Issue(mockRestClient, JSONSerializer.toJSON(JSONResources.ISSUE) as JSONObject)
}
static void "Assert equals to Board"(Board board) {
assertThat board, new IsNot<>(new IsNull())
assertThat board.getId(), new IsEqual<Long>(JSONResources.BOARD_ID)
assertThat board.getName(), new IsEqual<String>(JSONResources.BOARD_NAME)
assertThat board.getType(), new IsEqual<String>(JSONResources.BOARD_TYPE)
assertThat board.getSelfURL(), new IsEqual<String>(JSONResources.BOARD_SELF)
assertThat board.toString(), new IsEqual<String>(
String.format("Board{id=%s, name='%s'}",
JSONResources.BOARD_ID, JSONResources.BOARD_NAME))
}
static void "Assert equals to Sprint"(Sprint sprint) {
assertThat sprint, new IsNot<>(new IsNull())
assertThat sprint.getId(), new IsEqual<Long>(JSONResources.SPRINT_ID)
assertThat sprint.getName(), new IsEqual<String>(JSONResources.SPRINT_NAME)
assertThat sprint.getSelfURL(), new IsEqual<String>(JSONResources.SPRINT_SELF)
assertThat sprint.getState(), new IsEqual<String>(JSONResources.SPRINT_STATE)
assertThat sprint.getOriginBoardId(), new IsEqual<Long>(JSONResources.SPRINT_ORIGIN_BOARD_ID)
assertThat sprint.getStartDate(), new IsEqual<Date>(JSONResources.SPRINT_START_DATE)
assertThat sprint.getEndDate(), new IsEqual<Date>(JSONResources.SPRINT_END_DATE)
assertThat sprint.getCompleteDate(), new IsEqual<Date>(JSONResources.SPRINT_COMPLETE_DATE)
assertThat sprint.toString(), new IsEqual<String>(
String.format("Sprint{id=%s, name='%s'}",
JSONResources.SPRINT_ID, JSONResources.SPRINT_NAME))
}
static void "Assert equals to Epic"(Epic epic) {
assertThat epic, new IsNot<>(new IsNull())
assertThat epic.getId(), new IsEqual<Long>(JSONResources.EPIC_ID)
assertThat epic.getName(), new IsEqual<String>(JSONResources.EPIC_NAME)
assertThat epic.getSelfURL(), new IsEqual<String>(JSONResources.EPIC_SELF)
assertThat epic.getKey(), new IsEqual<String>(JSONResources.EPIC_KEY)
assertThat epic.getSummary(), new IsEqual<String>(JSONResources.EPIC_SUMMARY)
assertThat epic.isDone(), new IsEqual<Boolean>(JSONResources.EPIC_DONE)
assertThat epic.toString(), new IsEqual<String>(
String.format("Epic{id=%s, name='%s'}",
JSONResources.EPIC_ID, JSONResources.EPIC_NAME))
}
static void "Assert equals to Project"(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)
assertThat project.getKey(), new IsEqual<String>(JSONResources.PROJECT_KEY)
assertThat project.toString(), new IsEqual<String>(
String.format("Project{id=%s, name='%s'}",
JSONResources.PROJECT_ID, JSONResources.PROJECT_NAME))
}
static void "Assert equals to Comment"(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)
assertThat comment.getBody(), new IsEqual<String>(JSONResources.ISSUE_COMMENT_BODY)
assertThat comment.getCreated(), new IsEqual<Date>(JSONResources.ISSUE_COMMENT_CREATED)
assertThat comment.getUpdated(), new IsEqual<Date>(JSONResources.ISSUE_COMMENT_UPDATED)
"Assert equals to User"(comment.getAuthor())
"Assert equals to User"(comment.getUpdateAuthor())
assertThat comment.toString(), new IsEqual<String>(
String.format("Comment{id=%s, body='%s'}",
JSONResources.ISSUE_COMMENT_ID, JSONResources.ISSUE_COMMENT_BODY))
}
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>()
assertThat timeTracking.getOriginalEstimate(), new IsEqual<String>(JSONResources.ISSUE_TIMETRACKING_ORIGINAL_ESTIMATE)
assertThat timeTracking.getRemainingEstimate(), new IsEqual<String>(JSONResources.ISSUE_TIMETRACKING_REMAINING_ESTIMATE)
assertThat timeTracking.getTimeSpent(), new IsEqual<String>(JSONResources.ISSUE_TIMETRACKING_TIME_SPENT)
assertThat timeTracking.getOriginalEstimateSeconds(), new IsEqual<Long>(JSONResources.ISSUE_TIMETRACKING_ORIGINAL_ESTIMATE_SECONDS)
assertThat timeTracking.getRemainingEstimateSeconds(), new IsEqual<Long>(JSONResources.ISSUE_TIMETRACKING_REMAINING_ESTIMATE_SECONDS)
assertThat timeTracking.getTimeSpentSeconds(), new IsEqual<Long>(JSONResources.ISSUE_TIMETRACKING_TIME_SPENT_SECONDS)
assertThat timeTracking.toString(), new IsEqual<String>(
String.format("TimeTracking{original='%s', remaining='%s', timeSpent='%s'}",
JSONResources.ISSUE_TIMETRACKING_ORIGINAL_ESTIMATE,
JSONResources.ISSUE_TIMETRACKING_REMAINING_ESTIMATE,
JSONResources.ISSUE_TIMETRACKING_TIME_SPENT))
}
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)
assertThat issueType.getDescription(), new IsEqual<String>(JSONResources.ISSUE_TYPE_DESCRIPTION)
assertThat issueType.isSubTask(), new IsEqual<Boolean>(JSONResources.ISSUE_TYPE_SUB_TASK)
assertThat issueType.toString(), new IsEqual<String>(
String.format("IssueType{id=%s, name='%s'}",
JSONResources.ISSUE_TYPE_ID, JSONResources.ISSUE_TYPE_NAME))
}
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)
assertThat status.getDescription(), new IsEqual<String>(JSONResources.ISSUE_STATUS_DESCRIPTION)
assertThat status.toString(), new IsEqual<String>(
String.format("Status{id=%s, name='%s'}",
JSONResources.ISSUE_STATUS_ID, JSONResources.ISSUE_STATUS_NAME))
}
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)
assertThat resolution.getDescription(), new IsEqual<String>(JSONResources.ISSUE_RESOLUTION_DESCRIPTION)
assertThat resolution.toString(), new IsEqual<String>(
String.format("Resolution{id=%s, name='%s'}",
JSONResources.ISSUE_RESOLUTION_ID, JSONResources.ISSUE_RESOLUTION_NAME))
}
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)
assertThat priority.toString(), new IsEqual<String>(
String.format("Priority{id=%s, name='%s'}",
JSONResources.ISSUE_PRIORITY_ID, JSONResources.ISSUE_PRIORITY_NAME))
}
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)
assertThat user.getEmailAddress(), new IsEqual<String>(JSONResources.USER_EMAIL_ADDRESS)
assertThat user.getDisplayName(), new IsEqual<String>(JSONResources.USER_DISPLAY_NAME)
assertThat user.isActive(), new IsEqual<Boolean>(JSONResources.USER_ACTIVE)
assertThat user.getTimeZone(), new IsEqual<String>(JSONResources.USER_TIME_ZONE)
assertThat user.toString(), new IsEqual<String>(
String.format("User{name='%s', Display Name='%s'}",
JSONResources.USER_NAME, JSONResources.USER_DISPLAY_NAME))
}
static void "Assert equals to Worklog"(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)
assertThat worklog.getComment(), new IsEqual<String>(JSONResources.ISSUE_WORKLOG_COMMENT)
assertThat worklog.getCreated(), new IsEqual<Date>(JSONResources.ISSUE_WORKLOG_CREATED)
assertThat worklog.getUpdated(), new IsEqual<Date>(JSONResources.ISSUE_WORKLOG_UPDATED)
assertThat worklog.getStarted(), new IsEqual<Date>(JSONResources.ISSUE_WORKLOG_STARTED)
assertThat worklog.getTimeSpent(), new IsEqual<String>(JSONResources.ISSUE_WORKLOG_TIMESPEND)
assertThat worklog.getTimeSpentSeconds(), new IsEqual<Long>(JSONResources.ISSUE_WORKLOG_TIMESPEND_SECONDS)
"Assert equals to User"(worklog.getAuthor())
"Assert equals to User"(worklog.getUpdateAuthor())
assertThat worklog.toString(), new IsEqual<String>(
String.format("Worklog{id=%s, comment='%s'}",
JSONResources.ISSUE_WORKLOG_ID, JSONResources.ISSUE_WORKLOG_COMMENT))
}
static void "Assert equals to Issue"(Issue issue) {
assertThat issue, new IsNot<>(new IsNull())
assertThat issue.getAttribute("fields"), new IsNot<>(new IsNull())
assertThat issue.getId(), new IsEqual<Long>(JSONResources.ISSUE_ID)
assertThat issue.getName(), new IsEqual<String>(JSONResources.ISSUE_SUMMARY)
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())
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())
assertThat issue.getComments(), new IsNot<>(new IsNull<>())
assertThat issue.getComments().size(), new IsEqual<Integer>(1)
"Assert equals to Comment"(issue.getComments().get(0))
"Assert equals to Epic"(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))
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())
assertThat issue.toString(), new IsEqual<String>(
String.format("Issue{id=%s, name='%s'}",
JSONResources.ISSUE_ID, JSONResources.ISSUE_SUMMARY))
}
static void "Assert equals to Issue Blank"(Issue issue) {
assertThat issue, new IsNot<>(new IsNull())
assertThat issue.getAttribute("fields"), 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)
assertThat issue.toString(), new IsEqual<String>(
String.format("Issue{id=%s, name='%s'}",
JSONResources.BLANK_ISSUE1_ID, null))
}
}

View File

@ -0,0 +1,87 @@
package net.rcarz.jiraclient.agile
import net.sf.json.JSONSerializer
import org.hamcrest.core.IsEqual
import org.hamcrest.core.IsNot
import org.hamcrest.core.IsNull
import org.junit.Test
import static org.junit.Assert.assertThat
import static org.mockito.Mockito.when
/**
* Created on 2016-05-19.
* @author pldupont
*/
class AgileClientTest extends AbstractResourceTest {
@Test
void "Given an agileClient, when calling getBoards(), then receive a list of Board."() {
"given an Agile Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "board"))
.thenReturn(JSONSerializer.toJSON(JSONResources.LIST_OF_BOARDS))
List<Board> boards = agileClient.getBoards();
assertThat boards, new IsNot<>(new IsNull())
assertThat boards.size(), new IsEqual<Integer>(2)
"Assert equals to Board"(boards.get(0))
}
@Test
void "Given an agileClient, when calling getBoard(boardId), then receive one Board."() {
"given an Agile Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "board/" + JSONResources.BOARD_ID))
.thenReturn(JSONSerializer.toJSON(JSONResources.BOARD))
Board board = agileClient.getBoard(JSONResources.BOARD_ID);
assertThat board, new IsNot<>(new IsNull())
"Assert equals to Board"(board)
}
@Test
void "Given an agileClient, when calling getSprint(sprintId), then receive one Sprint."() {
"given an Agile Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "sprint/" + JSONResources.SPRINT_ID))
.thenReturn(JSONSerializer.toJSON(JSONResources.SPRINT))
Sprint sprint = agileClient.getSprint(JSONResources.SPRINT_ID);
assertThat sprint, new IsNot<>(new IsNull())
"Assert equals to Sprint"(sprint)
}
@Test
void "Given an agileClient, when calling getIssue(id), then receive one Issue."() {
"given an Agile Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "issue/" + JSONResources.ISSUE_ID))
.thenReturn(JSONSerializer.toJSON(JSONResources.ISSUE))
Issue issue = agileClient.getIssue(JSONResources.ISSUE_ID);
"Assert equals to Issue"(issue)
}
@Test
void "Given an agileClient, when calling getIssue(key), then receive one Issue."() {
"given an Agile Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "issue/" + JSONResources.ISSUE_KEY))
.thenReturn(JSONSerializer.toJSON(JSONResources.ISSUE))
Issue issue = agileClient.getIssue(JSONResources.ISSUE_KEY);
"Assert equals to Issue"(issue)
}
@Test
void "Given an agileClient, when calling getEpic(id), then receive one Epic."() {
"given an Agile Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "epic/" + JSONResources.EPIC_ID))
.thenReturn(JSONSerializer.toJSON(JSONResources.EPIC))
Epic epic = agileClient.getEpic(JSONResources.EPIC_ID);
"Assert equals to Epic"(epic)
}
}

View File

@ -0,0 +1,91 @@
package net.rcarz.jiraclient.agile
import net.rcarz.jiraclient.JiraException
import net.sf.json.JSONSerializer
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
/**
* Test for edge cases on deserialization.
* @author pldupont
*/
class AgileResourceTest extends AbstractResourceTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
void "given a valid single resource JSON and a valid type, when calling getResource(), then should return an object"() {
def aRESTClient = "given a REST Client"()
def aValidResource = JSONSerializer.toJSON(JSONResources.BOARD)
def resource = AgileResource.getResource(Board.class, aValidResource, aRESTClient)
assertThat resource, new IsNot<>(new IsNull())
}
@Test
void "given an invalid single resource JSON and a valid type, when calling getResource(), then should throw an exception"() {
def aRESTClient = "given a REST Client"()
def anInvalidResource = JSONResources.BOARD
expectedException.expectMessage("JSON payload is malformed")
expectedException.expect(JiraException.class)
AgileResource.getResource(Board.class, anInvalidResource, aRESTClient)
}
@Test
void "given a valid single resource JSON and an invalid type, when calling getResource(), then should throw an exception"() {
def aRESTClient = "given a REST Client"()
def aValidResource = JSONSerializer.toJSON(JSONResources.BOARD)
expectedException.expectMessage("Failed to deserialize object.")
expectedException.expect(JiraException.class)
AgileResource.getResource(String.class, aValidResource, aRESTClient)
}
@Test
void "given a valid resource array JSON and a valid type, when calling getResource(), then should return an object"() {
def aRESTClient = "given a REST Client"()
def aValidResource = JSONSerializer.toJSON(JSONResources.LIST_OF_BOARDS)
def resource = AgileResource.getResourceArray(Board.class, aValidResource, aRESTClient, "values")
assertThat resource, new IsNot<>(new IsNull())
}
@Test
void "given a valid resource array JSON and a valid type but list name invalid, when calling getResource(), then should return an object"() {
def aRESTClient = "given a REST Client"()
def aValidResource = JSONSerializer.toJSON(JSONResources.LIST_OF_BOARDS)
expectedException.expectMessage("No array found for name 'v'")
expectedException.expect(JiraException.class)
AgileResource.getResourceArray(Board.class, aValidResource, aRESTClient, "v")
}
@Test
void "given an invalid resource array JSON and a valid type, when calling getResource(), then should throw an exception"() {
def aRESTClient = "given a REST Client"()
def anInvalidResource = JSONResources.LIST_OF_BOARDS
expectedException.expectMessage("JSON payload is malformed")
expectedException.expect(JiraException.class)
AgileResource.getResourceArray(Board.class, anInvalidResource, aRESTClient, "values")
}
@Test
void "given a valid resource array JSON and an invalid type, when calling getResource(), then should throw an exception"() {
def aRESTClient = "given a REST Client"()
def aValidResource = JSONSerializer.toJSON(JSONResources.LIST_OF_BOARDS)
expectedException.expectMessage("Failed to deserialize object.")
expectedException.expect(JiraException.class)
AgileResource.getResourceArray(String.class, aValidResource, aRESTClient, "values")
}
}

View File

@ -0,0 +1,130 @@
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
/**
* Created on 2016-05-19.
* @author pldupont
*/
class BoardTest extends AbstractResourceTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
void "Given a RestClient, when calling getAll(), then receive a list of Board."() {
RestClient mockRestClient = "given a REST Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "board"))
.thenReturn(JSONSerializer.toJSON(JSONResources.LIST_OF_BOARDS))
List<Board> boards = Board.getAll(mockRestClient);
assertThat boards, new IsNot<>(new IsNull())
assertThat boards.size(), new IsEqual<Integer>(2)
"Assert equals to Board"(boards.get(0))
}
@Test
void "Given a RestClient, when calling getAll() and use doesn't have access, then throws an 401 error."() {
RestException unauthorized = new RestException("Do not have access", 401, "Unauthorized")
RestClient mockRestClient = "given a REST Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "board"))
.thenThrow(unauthorized)
expectedException.expect(JiraException.class);
expectedException.expectMessage("Failed to retrieve a list of Board : /rest/agile/1.0/board");
Board.getAll(mockRestClient);
}
@Test
void "Given a RestClient, when calling getBoard(boardId), then receive one Board."() {
RestClient mockRestClient = "given a REST Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "board/${JSONResources.BOARD_ID}"))
.thenReturn(JSONSerializer.toJSON(JSONResources.BOARD))
Board board = Board.get(mockRestClient, JSONResources.BOARD_ID);
"Assert equals to Board"(board)
}
@Test
void "Given a RestClient, when calling getBoard(666), then throws an 404 error."() {
RestException unauthorized = new RestException("Do not have access", 404, "Unauthorized")
RestClient mockRestClient = "given a REST Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "board/666"))
.thenThrow(unauthorized)
expectedException.expect(JiraException.class);
expectedException.expectMessage("Failed to retrieve Board : /rest/agile/1.0/board/666");
Board.get(mockRestClient, 666);
}
@Test
void "Given a valid Board, when calling getSprints(), then receive a list of Sprints."() {
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}/sprint"))
.thenReturn(JSONSerializer.toJSON(JSONResources.LIST_OF_SPRINTS))
List<Sprint> sprints = mockBoard.getSprints();
assertThat sprints, new IsNot<>(new IsNull())
assertThat sprints.size(), new IsEqual<Integer>(2)
"Assert equals to Sprint"(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"(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"(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"(issues.get(0))
}
}

View File

@ -0,0 +1,109 @@
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
/**
* Created on 2016-05-20.
* @author pldupont
*/
class EpicTest extends AbstractResourceTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
void "Given a valid Epic ID, when calling Epic.get(id), then receive one Epic."() {
RestClient mockRestClient = "given a REST Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "epic/" + JSONResources.EPIC_ID))
.thenReturn(JSONSerializer.toJSON(JSONResources.EPIC))
Epic epic = Epic.get(mockRestClient, JSONResources.EPIC_ID);
"Assert equals to Epic"(epic)
}
@Test
void "Given an invalid epic ID, when calling getEpic(666), then throws an 404 error."() {
RestException unauthorized = new RestException("Do not have access", 404, "Unauthorized")
RestClient mockRestClient = "given a REST Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "epic/666"))
.thenThrow(unauthorized)
expectedException.expect(JiraException.class);
expectedException.expectMessage("Failed to retrieve Epic : /rest/agile/1.0/epic/666");
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"(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"(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"(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"(issues.get(0))
}
}

View File

@ -0,0 +1,78 @@
package net.rcarz.jiraclient.agile
import net.rcarz.jiraclient.JiraException
import net.rcarz.jiraclient.RestClient
import net.rcarz.jiraclient.RestException
import net.sf.json.JSONSerializer
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import static org.mockito.Mockito.when
/**
* Created on 2016-05-20.
* @author pldupont
*/
class IssueTest extends AbstractResourceTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
void "Given a valid issue ID, when calling Issue.get(id), then receive one Issue."() {
RestClient mockRestClient = "given a REST Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "issue/" + JSONResources.ISSUE_ID))
.thenReturn(JSONSerializer.toJSON(JSONResources.ISSUE))
Issue issue = Issue.get(mockRestClient, JSONResources.ISSUE_ID);
"Assert equals to Issue"(issue)
}
@Test
void "Given an invalid issue ID, when calling getIssue(666), then throws an 404 error."() {
RestException unauthorized = new RestException("Do not have access", 404, "Unauthorized")
RestClient mockRestClient = "given a REST Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "issue/666"))
.thenThrow(unauthorized)
expectedException.expect(JiraException.class);
expectedException.expectMessage("Failed to retrieve Issue : /rest/agile/1.0/issue/666");
Issue.get(mockRestClient, 666);
}
@Test
void "Given a valid issue Key, when calling Issue.get(key), then receive one Issue."() {
RestClient mockRestClient = "given a REST Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "issue/" + JSONResources.ISSUE_KEY))
.thenReturn(JSONSerializer.toJSON(JSONResources.ISSUE))
Issue issue = Issue.get(mockRestClient, JSONResources.ISSUE_KEY);
"Assert equals to Issue"(issue)
}
@Test
void "Given an invalid issue Key, when calling getIssue('HSP-2'), then throws an 404 error."() {
RestException unauthorized = new RestException("Do not have access", 404, "Unauthorized")
RestClient mockRestClient = "given a REST Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "issue/HSP-2"))
.thenThrow(unauthorized)
expectedException.expect(JiraException.class);
expectedException.expectMessage("Failed to retrieve Issue : /rest/agile/1.0/issue/HSP-2");
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 Blank"(issue)
}
}

View File

@ -0,0 +1,495 @@
package net.rcarz.jiraclient.agile
import net.rcarz.jiraclient.Field
/**
* Created on 2016-05-19.
* @author pldupont
*/
interface JSONResources {
long BOARD_ID = 84L
String BOARD_SELF = "http://www.example.com/jira/rest/agile/1.0/board/${BOARD_ID}"
String BOARD_NAME = "scrum board"
String BOARD_TYPE = "scrum"
String BOARD = """{
"id": ${BOARD_ID},
"self": "${BOARD_SELF}",
"name": "${BOARD_NAME}",
"type": "${BOARD_TYPE}"
}"""
String LIST_OF_BOARDS = """{
"maxResults": 2,
"startAt": 1,
"total": 2,
"isLast": true,
"values": [
${BOARD},
{
"id": 92,
"self": "http://www.example.com/jira/rest/agile/1.0/board/92",
"name": "kanban board",
"type": "kanban"
}
]
}"""
long SPRINT_ID = 37L
String SPRINT_NAME = "sprint 1"
String SPRINT_SELF = "http://www.example.com/jira/rest/agile/1.0/sprint/${SPRINT_ID}"
String SPRINT_STATE = "closed"
long SPRINT_ORIGIN_BOARD_ID = BOARD_ID
String SPRINT_START_DATE_STR = "2015-04-11T15:22:00.000+10:00"
Date SPRINT_START_DATE = Field.getDateTime(SPRINT_START_DATE_STR)
String SPRINT_END_DATE_STR = "2015-04-20T01:22:00.000+10:00"
Date SPRINT_END_DATE = Field.getDateTime(SPRINT_END_DATE_STR)
String SPRINT_COMPLETE_DATE_STR = "2015-04-20T11:04:00.000+10:00"
Date SPRINT_COMPLETE_DATE = Field.getDateTime(SPRINT_COMPLETE_DATE_STR)
String SPRINT = """{
"id": ${SPRINT_ID},
"self": "${SPRINT_SELF}",
"state": "${SPRINT_STATE}",
"name": "${SPRINT_NAME}",
"startDate": "${SPRINT_START_DATE_STR}",
"endDate": "${SPRINT_END_DATE_STR}",
"completeDate": "${SPRINT_COMPLETE_DATE_STR}",
"originBoardId": ${BOARD_ID}
}"""
String LIST_OF_SPRINTS = """{
"maxResults": 2,
"startAt": 1,
"total": 2,
"isLast": true,
"values": [
${SPRINT},
{
"id": 72,
"self": "http://www.example.com/jira/rest/agile/1.0/sprint/73",
"state": "future",
"name": "sprint 2"
}
]
}"""
long EPIC_ID = 23
String EPIC_SELF = "http://www.example.com/jira/rest/agile/1.0/epic/${EPIC_ID}"
String EPIC_NAME = "epic 1"
String EPIC_KEY = "EX"
String EPIC_SUMMARY = "epic 1 summary"
boolean EPIC_DONE = true
String EPIC = """{
"id": ${EPIC_ID},
"self": "${EPIC_SELF}",
"name": "${EPIC_NAME}",
"key": "${EPIC_KEY}",
"summary": "${EPIC_SUMMARY}",
"color": {
"key": "color_4"
},
"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 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",
"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"
}
}"""
String USER_NAME = "Example"
String USER_SELF = "https://www.example.com/rest/api/2/user?username=${USER_NAME}"
String USER_EMAIL_ADDRESS = "pldupont@example.com"
String USER_DISPLAY_NAME = "Pierre-Luc Dupont"
boolean USER_ACTIVE = true
String USER_TIME_ZONE = "America/New_York"
String USER = """{
"self" : "${USER_SELF}",
"name" : "${USER_NAME}",
"key" : "pldupont",
"emailAddress" : "${USER_EMAIL_ADDRESS}",
"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" : "${USER_DISPLAY_NAME}",
"active" : ${USER_ACTIVE},
"timeZone" : "${USER_TIME_ZONE}"
}"""
String ISSUE_TIMETRACKING_ORIGINAL_ESTIMATE = "10m"
String ISSUE_TIMETRACKING_REMAINING_ESTIMATE = "3m"
String ISSUE_TIMETRACKING_TIME_SPENT = "6m"
long ISSUE_TIMETRACKING_ORIGINAL_ESTIMATE_SECONDS = 600L
long ISSUE_TIMETRACKING_REMAINING_ESTIMATE_SECONDS = 200L
long ISSUE_TIMETRACKING_TIME_SPENT_SECONDS = 400L
String ISSUE_TIMETRACKING = """{
"originalEstimate": "${ISSUE_TIMETRACKING_ORIGINAL_ESTIMATE}",
"remainingEstimate": "${ISSUE_TIMETRACKING_REMAINING_ESTIMATE}",
"timeSpent": "${ISSUE_TIMETRACKING_TIME_SPENT}",
"originalEstimateSeconds": ${ISSUE_TIMETRACKING_ORIGINAL_ESTIMATE_SECONDS},
"remainingEstimateSeconds": ${ISSUE_TIMETRACKING_REMAINING_ESTIMATE_SECONDS},
"timeSpentSeconds": ${ISSUE_TIMETRACKING_TIME_SPENT_SECONDS}
}"""
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_COMMENT = "I did some work here."
String ISSUE_WORKLOG_CREATED_STR = "2016-03-21T15:25:17.882+0100"
Date ISSUE_WORKLOG_CREATED = Field.getDateTime(ISSUE_WORKLOG_CREATED_STR)
String ISSUE_WORKLOG_UPDATED_STR = "2016-03-21T15:26:17.882+0100"
Date ISSUE_WORKLOG_UPDATED = Field.getDateTime(ISSUE_WORKLOG_UPDATED_STR)
String ISSUE_WORKLOG_STARTED_STR = "2016-03-21T15:26:17.881+0100"
Date ISSUE_WORKLOG_STARTED = Field.getDateTime(ISSUE_WORKLOG_STARTED_STR)
String ISSUE_WORKLOG_TIMESPEND = "3h 20m"
long ISSUE_WORKLOG_TIMESPEND_SECONDS = 12000
String ISSUE_WORKLOG = """{
"self": "${ISSUE_WORKLOG_SELF}",
"author": ${USER},
"updateAuthor": ${USER},
"comment": "${ISSUE_WORKLOG_COMMENT}",
"created": "${ISSUE_WORKLOG_CREATED_STR}",
"updated": "${ISSUE_WORKLOG_UPDATED_STR}",
"visibility": {
"type": "group",
"value": "jira-developers"
},
"started": "${ISSUE_WORKLOG_STARTED_STR}",
"timeSpent": "${ISSUE_WORKLOG_TIMESPEND}",
"timeSpentSeconds": ${ISSUE_WORKLOG_TIMESPEND_SECONDS},
"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_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."
String ISSUE_COMMENT_CREATED_STR = "2016-05-11T10:58:01.000-0400"
Date ISSUE_COMMENT_CREATED = Field.getDateTime(ISSUE_COMMENT_CREATED_STR)
String ISSUE_COMMENT_UPDATED_STR = "2016-05-30T14:20:29.000-0400"
Date ISSUE_COMMENT_UPDATED = Field.getDateTime(ISSUE_COMMENT_UPDATED_STR)
String ISSUE_COMMENT = """{
"self": "${ISSUE_COMMENT_SELF}",
"id": "${ISSUE_COMMENT_ID}",
"author": ${USER},
"body": "${ISSUE_COMMENT_BODY}",
"updateAuthor": ${USER},
"created": "${ISSUE_COMMENT_CREATED_STR}",
"updated": "${ISSUE_COMMENT_UPDATED_STR}",
"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_DESCRIPTION = "A problem which impairs or prevents the functions of the product."
boolean ISSUE_TYPE_SUB_TASK = true
String ISSUE_TYPE = """{
"self" : "${ISSUE_TYPE_SELF}",
"id" : "${ISSUE_TYPE_ID}",
"description" : "${ISSUE_TYPE_DESCRIPTION}",
"iconUrl" : "https://www.example.com/images/icons/issuetypes/bug.png",
"name" : "${ISSUE_TYPE_NAME}",
"subtask" : ${ISSUE_TYPE_SUB_TASK}
}"""
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_DESCRIPTION = "The problem is not a problem"
String ISSUE_RESOLUTION = """{
"self" : "${ISSUE_RESOLUTION_SELF}",
"id" : "${ISSUE_RESOLUTION_ID}",
"description" : "${ISSUE_RESOLUTION_DESCRIPTION}",
"name" : "${ISSUE_RESOLUTION_NAME}"
}"""
long ISSUE_STATUS_ID = 6L
String ISSUE_STATUS_NAME = "Closed"
String ISSUE_STATUS_DESCRIPTION = "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened."
String ISSUE_STATUS_SELF = "https://www.example.com/rest/api/2/status/${ISSUE_STATUS_ID}"
String ISSUE_STATUS = """{
"self" : "${ISSUE_STATUS_SELF}",
"description" : "${ISSUE_STATUS_DESCRIPTION}",
"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"
String ISSUE_SUMMARY = "Issue summary"
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},
"summary": "${ISSUE_SUMMARY}",
"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}
]
},
"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

@ -0,0 +1,88 @@
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
/**
* Created on 2016-05-19.
* @author pldupont
*/
class SprintTest extends AbstractResourceTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
void "Given a RestClient, when calling getAll(), then receive a list of Sprint."() {
RestClient mockRestClient = "given a REST Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "board/" + JSONResources.SPRINT_ORIGIN_BOARD_ID + "/sprint"))
.thenReturn(JSONSerializer.toJSON(JSONResources.LIST_OF_SPRINTS))
List<Sprint> sprints = Sprint.getAll(mockRestClient, JSONResources.SPRINT_ORIGIN_BOARD_ID);
assertThat sprints, new IsNot<>(new IsNull())
assertThat sprints.size(), new IsEqual<Integer>(2)
"Assert equals to Sprint"(sprints.get(0))
}
@Test
void "Given a RestClient, when calling getAll() and use doesn't have access, then throws an 401 error."() {
RestException unauthorized = new RestException("Do not have access", 401, "Unauthorized")
RestClient mockRestClient = "given a REST Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "board/" + JSONResources.SPRINT_ORIGIN_BOARD_ID + "/sprint"))
.thenThrow(unauthorized)
expectedException.expect(JiraException.class);
expectedException.expectMessage("Failed to retrieve a list of Sprint : /rest/agile/1.0/board/" + JSONResources.SPRINT_ORIGIN_BOARD_ID + "/sprint");
Sprint.getAll(mockRestClient, JSONResources.SPRINT_ORIGIN_BOARD_ID);
}
@Test
void "Given a RestClient, when calling getSprint(sprintId), then receive one Sprint."() {
RestClient mockRestClient = "given a REST Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "sprint/${JSONResources.SPRINT_ID}"))
.thenReturn(JSONSerializer.toJSON(JSONResources.SPRINT))
Sprint sprint = Sprint.get(mockRestClient, JSONResources.SPRINT_ID);
"Assert equals to Sprint"(sprint)
}
@Test
void "Given a RestClient, when calling getSprint(666), then throws an 404 error."() {
RestException unauthorized = new RestException("Do not have access", 404, "Unauthorized")
RestClient mockRestClient = "given a REST Client"()
when(mockRestClient.get(AgileResource.RESOURCE_URI + "sprint/666"))
.thenThrow(unauthorized)
expectedException.expect(JiraException.class);
expectedException.expectMessage("Failed to retrieve Sprint : /rest/agile/1.0/sprint/666");
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"(issues.get(0))
}
}