bugherd_client 0.0.6 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rspec +2 -1
  4. data/.travis.yml +4 -1
  5. data/README.md +23 -38
  6. data/Rakefile +6 -1
  7. data/bin/console +17 -0
  8. data/bugherd_client.gemspec +17 -13
  9. data/lib/bugherd_client.rb +19 -16
  10. data/lib/bugherd_client/client.rb +44 -18
  11. data/lib/bugherd_client/errors.rb +19 -5
  12. data/lib/bugherd_client/resources/v1/base.rb +2 -2
  13. data/lib/bugherd_client/resources/v1/comment.rb +1 -1
  14. data/lib/bugherd_client/resources/v1/project.rb +4 -4
  15. data/lib/bugherd_client/resources/v1/task.rb +11 -8
  16. data/lib/bugherd_client/resources/v2/attachment.rb +73 -0
  17. data/lib/bugherd_client/resources/v2/base.rb +24 -5
  18. data/lib/bugherd_client/resources/v2/comment.rb +2 -2
  19. data/lib/bugherd_client/resources/v2/organization.rb +5 -5
  20. data/lib/bugherd_client/resources/v2/project.rb +22 -13
  21. data/lib/bugherd_client/resources/v2/task.rb +34 -14
  22. data/lib/bugherd_client/resources/v2/webhook.rb +54 -0
  23. data/lib/bugherd_client/version.rb +1 -1
  24. data/spec/bugherd_client/client_spec.rb +63 -11
  25. data/spec/bugherd_client/v2/organization_spec.rb +21 -0
  26. data/spec/bugherd_client/v2/project_spec.rb +66 -0
  27. data/spec/bugherd_client/v2/task_spec.rb +46 -0
  28. data/spec/bugherd_client/v2/user_spec.rb +50 -0
  29. data/spec/bugherd_client/v2/webhook_spec.rb +20 -0
  30. data/spec/cassettes/guests_all.yml +64 -0
  31. data/spec/cassettes/members_all.yml +66 -0
  32. data/spec/cassettes/organizations_get.yml +62 -0
  33. data/spec/cassettes/projects_active.yml +65 -0
  34. data/spec/cassettes/projects_all.yml +65 -0
  35. data/spec/cassettes/projects_find_failure.yml +60 -0
  36. data/spec/cassettes/projects_find_success.yml +65 -0
  37. data/spec/cassettes/tasks_all.yml +87 -0
  38. data/spec/cassettes/tasks_find_success.yml +69 -0
  39. data/spec/cassettes/users_all.yml +66 -0
  40. data/spec/cassettes/webhooks_all.yml +64 -0
  41. data/spec/spec_helper.rb +23 -9
  42. data/spec/support/http_helper.rb +7 -0
  43. metadata +130 -23
@@ -12,7 +12,7 @@ module BugherdClient
12
12
  STATUSES = ['feedback', 'backlog','todo','doing','done','closed']
13
13
  STATUSES.each.with_index do |status, index|
14
14
  if index == 0
15
- Task.const_set("STATUS_#{status.upcase}", nil)
15
+ Task.const_set("STATUS_#{status.upcase}", nil)
16
16
  else
17
17
  Task.const_set("STATUS_#{status.upcase}", index-1)
18
18
  end
@@ -37,15 +37,15 @@ module BugherdClient
37
37
 
38
38
  #
39
39
  # Create a new Task
40
- # attributes:
41
- # description, priority, status, tag_names(Array),
42
- # requester_id or requester_email,
40
+ # attributes:
41
+ # description, priority, status, tag_names(Array),
42
+ # requester_id or requester_email,
43
43
  # assigned_to_id or assigned_to_email
44
44
  # external_id
45
45
  # if status is null the Task is automatically put in the Feedback panel
46
- # "requester_email" can be any email address while "assigned_to_email" needs to be of a current project member.
47
- # Values for "priority" are not set, critical, important, normal, and minor.
48
- # Values for "status" are backlog, todo, doing, done, and closed. Omit this field or set as "null" to send tasks to the Feedback panel.
46
+ # 'requester_email' can be any email address while 'assigned_to_email' needs to be of a current project member.
47
+ # Values for 'priority' are not set, critical, important, normal, and minor.
48
+ # Values for 'status' are backlog, todo, doing, done, and closed. Omit this field or set as 'null' to send tasks to the Feedback panel.
49
49
  # External ID is an API-only field. It cannot be set from the BugHerd application, only using the API. An external ID can be used to track originating IDs from other systems in BugHerd bugs.
50
50
  def create(project_id, attributes={})
51
51
  raw_response = post_request("projects/#{project_id}/tasks", task: attributes)
@@ -57,8 +57,11 @@ module BugherdClient
57
57
  parse_response(raw_response)
58
58
  end
59
59
 
60
+ def delete(project_id, task_id)
61
+ end
62
+
60
63
  end
61
64
 
62
65
  end
63
66
  end
64
- end
67
+ end
@@ -0,0 +1,73 @@
1
+ module BugherdClient
2
+ module Resources
3
+ module V2
4
+
5
+ class Attachment < Base
6
+
7
+ # LIST
8
+ #
9
+ # Get a paginated list of attachments for a task.
10
+ # GET /api_v2/projects/#{project_id}/tasks/#{task_id}/attachments.json
11
+ def all(project_id, task_id)
12
+ raw_response = get_request("projects/#{project_id}/tasks/#{task_id}/attachments")
13
+ parse_response(raw_response, :attachments)
14
+ end
15
+
16
+ # SHOW
17
+ #
18
+ # Get detail for specific attachment.
19
+ # GET /api_v2/projects/#{project_id}/tasks/#{task_id}/attachments/#{id}.json
20
+ def find(project_id, task_id, attachment_id)
21
+ raw_response = get_request("projects/#{project_id}/tasks/#{task_id}/attachments/#{attachment_id}")
22
+ parse_response(raw_response)
23
+ end
24
+
25
+ # CREATE
26
+ #
27
+ # Adds a new attachment to the specified task using an existing URL.
28
+ # POST /api_v2/projects/#{project_id}/tasks/#{task_id}/attachments.json
29
+ #
30
+ # PARAMS
31
+ # {'attachment':{
32
+ # 'file_name':'resolution.gif',
33
+ # 'url':'http://i.imgur.com/U9h3jZI.gif'
34
+ # }}
35
+ def create(project_id, task_id, payload)
36
+ raw_response = post_request("projects/#{project_id}/tasks/#{task_id}/attachments", attachment: payload)
37
+ parse_response(raw_response, :attachment)
38
+ end
39
+
40
+ # UPLOAD
41
+ #
42
+ # Upload a new attachment and add it to the specified task.
43
+ # The file contents need to be specified as the POST data on this request.
44
+ #
45
+ # Note that your upload needs to be reasonable in size as the maximum time the request
46
+ # may take is around 30 seconds.
47
+ # If you have larger uploads please create arrange your own file upload
48
+ # and create the attachment from a URL instead.
49
+ #
50
+ # POST /api_v2/projects/#{project_id}/tasks/#{task_id}/attachments/upload
51
+ #
52
+ # Note in the sample below please specify an existing file name.
53
+ def upload(project_id, task_id, payload)
54
+ uri = "projects/#{project_id}/tasks/#{task_id}/attachments/upload"
55
+ headers = { content_type: 'application/binary' }
56
+ raw_response = post_request(uri, payload.merge(headers: headers))
57
+ parse_response(raw_response, :attachment)
58
+ end
59
+
60
+ # DELETE
61
+ #
62
+ # Delete an attachment from a task. Note that this action is permanent and cannot be undone.
63
+ # DELETE /api_v2/projects/#{project_id}/tasks/#{task_id}/attachments/#{id}.json
64
+ def delete(project_id, task_id, attachment_id)
65
+ raw_response = delete_request("projects/#{project_id}/tasks/#{task_id}/attachments/#{attachment_id}")
66
+ parse_response(raw_response)
67
+ end
68
+
69
+ end
70
+
71
+ end # V2
72
+ end # Resources
73
+ end # BugherdClient
@@ -18,16 +18,22 @@ module BugherdClient
18
18
  self.class.instance_methods(false)
19
19
  end
20
20
 
21
- attr_accessor :connection, :options
21
+ # store a reference to the HTTP connection
22
+ attr_accessor :connection
23
+
24
+ attr_accessor :options
25
+
22
26
  def initialize(conn, opts={})
23
27
  @connection, @options = conn, opts
24
28
  end
25
29
 
26
- def send_request(method="GET", path="", params={}, headers={})
30
+ def send_request(method='GET', path='', params={}, headers={})
27
31
  headers = DEFAULT_HEADER_ATTRS.merge(headers)
28
32
  params.merge!(headers)
29
33
  method_name = method.to_s.downcase
30
34
  self.connection[path].__send__(method_name, params)
35
+ rescue RestClient::Exception => e
36
+ raise(BugherdClient::Errors::HttpRequestError.new(e.message, e.http_code))
31
37
  end
32
38
 
33
39
  [:get, :post, :put, :patch, :delete].each do |method_name|
@@ -36,16 +42,29 @@ module BugherdClient
36
42
  end
37
43
  end
38
44
 
45
+ def converter(body)
46
+ case body
47
+ when Hash
48
+ ::Hashie::Mash.new(body)
49
+ when Array
50
+ body.map { |item| item.is_a?(Hash) ? converter(item) : item }
51
+ else
52
+ body
53
+ end
54
+ end
55
+
39
56
  def parse_response(response, root_element=nil)
40
- if root_element
41
- JSON.parse(response)[root_element.to_s]
57
+ parsed = if root_element
58
+ p = JSON.parse(response)
59
+ p.key?(root_element.to_s) ? p[root_element.to_s] : p
42
60
  else
43
61
  JSON.parse(response)
44
62
  end
63
+ converter(parsed)
45
64
  end
46
65
 
47
66
  end
48
67
 
49
68
  end
50
69
  end
51
- end
70
+ end
@@ -1,7 +1,7 @@
1
1
  module BugherdClient
2
2
  module Resources
3
3
  module V2
4
-
4
+
5
5
  class Comment < Base
6
6
 
7
7
  #
@@ -31,4 +31,4 @@ module BugherdClient
31
31
 
32
32
  end
33
33
  end
34
- end
34
+ end
@@ -1,18 +1,18 @@
1
1
  module BugherdClient
2
2
  module Resources
3
3
  module V2
4
-
4
+
5
5
  class Organization < Base
6
6
 
7
7
  #
8
8
  # Get more detail of your account.
9
- #
9
+ #
10
10
  def get
11
11
  raw_response = self.connection['organization'].get
12
12
  parse_response(raw_response, :organization)
13
13
  end
14
14
  end
15
15
 
16
- end
17
- end
18
- end
16
+ end # V2
17
+ end # Resources
18
+ end # BugherdClient
@@ -6,7 +6,7 @@ module BugherdClient
6
6
 
7
7
  #
8
8
  # Get more detail of your account.
9
- #
9
+ #
10
10
  def all
11
11
  raw_response = get_request('projects')
12
12
  parse_response(raw_response, :projects)
@@ -14,18 +14,27 @@ module BugherdClient
14
14
 
15
15
  #
16
16
  # Show details for a specific project
17
- #
17
+ #
18
18
  def find(project_id)
19
19
  raw_response = get_request("projects/#{project_id}")
20
20
  parse_response(raw_response, :project)
21
21
  end
22
22
 
23
+ # CREATE
24
+ #
25
+ # Create a new project. The project will initially have no members.
26
+ # POST /api_v2/projects.json
27
+ #
28
+ # PARAMS:
29
+ # {
30
+ # "name": "My Website",
31
+ # "devurl": "http://www.example.com",
32
+ # "is_active": true,
33
+ # "is_public": false
34
+ # }
23
35
  #
24
- # Create a Project, will initially have no members
25
- # attributes: name, devurl, is_public, is_active
26
- #
27
36
  def create(attributes={})
28
- raw_response = post_request("projects", project: attributes)
37
+ raw_response = post_request('projects', project: attributes)
29
38
  parse_response(raw_response, :project)
30
39
  end
31
40
 
@@ -37,7 +46,7 @@ module BugherdClient
37
46
  parse_response(raw_response, :project)
38
47
  end
39
48
 
40
- #
49
+ #
41
50
  # Delete a project and all associated data. Use with care, deleted projects cannot be recovered.
42
51
  # API: 1,2
43
52
  def delete(project_id)
@@ -45,7 +54,7 @@ module BugherdClient
45
54
  parse_response(raw_response)
46
55
  end
47
56
 
48
- #
57
+ #
49
58
  # Add an existing guest to a project, or invite someone by email address.
50
59
  # required: project_id
51
60
  # attributes: user_id, email
@@ -55,11 +64,11 @@ module BugherdClient
55
64
  parse_response(raw_response)
56
65
  end
57
66
 
58
- #
67
+ #
59
68
  # Add an existing guest to a project, or invite someone by email address.
60
69
  # required: project_id
61
70
  # attributes: user_id
62
- #
71
+ #
63
72
  def add_member(project_id, attributes={})
64
73
  raw_response = post_request("projects/#{project_id}/add_member", attributes)
65
74
  parse_response(raw_response)
@@ -68,13 +77,13 @@ module BugherdClient
68
77
 
69
78
  #
70
79
  # Get all active projects
71
- #
80
+ #
72
81
  def active
73
82
  raw_response = get_request('projects/active')
74
83
  parse_response(raw_response, :projects)
75
84
  end
76
85
  end
77
-
86
+
78
87
  end
79
88
  end
80
- end
89
+ end
@@ -5,20 +5,31 @@ module BugherdClient
5
5
  class Task < Base
6
6
 
7
7
  PRIORITIES = ['not set', 'critical', 'important', 'normal','minor']
8
- PRIORITIES.each do |priority|
9
- Task.const_set("PRIORITY_#{priority.gsub(' ', '').upcase}", priority)
8
+ PRIORITIES.each { |p| Task.const_set("PRIORITY_#{p.gsub(' ', '').upcase}", p) }
9
+ def priorities
10
+ self.class::PRIORITIES
10
11
  end
11
12
 
12
- STATUSES = ['backlog','todo','doing','done','closed']
13
- STATUSES.each do |status|
14
- Task.const_set("STATUS_#{status.upcase}", status)
13
+ STATUSES = ['backlog','todo','doing','done','closed']
14
+ STATUSES.each { |s| Task.const_set("STATUS_#{s.upcase}", s) }
15
+ def statuses
16
+ self.class::STATUSES
15
17
  end
16
18
 
19
+ VALID_QUERY_KEYS = [:page, :updated_since, :created_since, :status, :priority, :assigned_to_id, :external_id]
20
+
17
21
  #
18
22
  # Get a full list of tasks for a project, including archived tasks.
19
- # filters: updated_since, created_since, status, priority, tag and external_id
23
+ # filters: updated_since, created_since, status, priority, tag,
24
+ # assigned_to_id, and external_id.
25
+ #
26
+ # example:
27
+ #
28
+ # client.tasks.all(45, { status: 'backlog' })
29
+ #
20
30
  def all(project_id, filter_attributes={})
21
31
  params = filter_attributes.empty? ? {} : { params: filter_attributes }
32
+ validate_filter_attributes!(filter_attributes) unless filter_attributes.empty?
22
33
  raw_response = get_request("projects/#{project_id}/tasks", params)
23
34
  parse_response(raw_response, :tasks)
24
35
  end
@@ -28,20 +39,20 @@ module BugherdClient
28
39
  #
29
40
  def find(project_id, task_id)
30
41
  raw_response = get_request("projects/#{project_id}/tasks/#{task_id}")
31
- parse_response(raw_response)
42
+ parse_response(raw_response, :task)
32
43
  end
33
44
 
34
45
  #
35
46
  # Create a new Task
36
- # attributes:
37
- # description, priority, status, tag_names(Array),
38
- # requester_id or requester_email,
47
+ # attributes:
48
+ # description, priority, status, tag_names(Array),
49
+ # requester_id or requester_email,
39
50
  # assigned_to_id or assigned_to_email
40
51
  # external_id
41
52
  # if status is null the Task is automatically put in the Feedback panel
42
- # "requester_email" can be any email address while "assigned_to_email" needs to be of a current project member.
43
- # Values for "priority" are not set, critical, important, normal, and minor.
44
- # Values for "status" are backlog, todo, doing, done, and closed. Omit this field or set as "null" to send tasks to the Feedback panel.
53
+ # 'requester_email' can be any email address while 'assigned_to_email' needs to be of a current project member.
54
+ # Values for 'priority' are not set, critical, important, normal, and minor.
55
+ # Values for 'status' are backlog, todo, doing, done, and closed. Omit this field or set as 'null' to send tasks to the Feedback panel.
45
56
  # External ID is an API-only field. It cannot be set from the BugHerd application, only using the API. An external ID can be used to track originating IDs from other systems in BugHerd bugs.
46
57
  def create(project_id, attributes={})
47
58
  raw_response = post_request("projects/#{project_id}/tasks", task: attributes)
@@ -53,8 +64,17 @@ module BugherdClient
53
64
  parse_response(raw_response)
54
65
  end
55
66
 
67
+ private
68
+ def validate_filter_attributes!(input_filters = {})
69
+ input_filters.keys.compact.each do |k|
70
+ unless VALID_QUERY_KEYS.include?(k.to_sym)
71
+ raise(BugherdClient::Errors::InvalidQueryKey.new(k, VALID_QUERY_KEYS))
72
+ end
73
+ end
74
+ end
75
+
56
76
  end
57
77
 
58
78
  end
59
79
  end
60
- end
80
+ end
@@ -0,0 +1,54 @@
1
+ module BugherdClient
2
+ module Resources
3
+ module V2
4
+ class Webhook < Base
5
+
6
+ EVENTS = ['task_create', 'task_update', 'task_destroy', 'comment']
7
+ def events
8
+ self.class::EVENTS
9
+ end
10
+
11
+ # LIST
12
+ #
13
+ # Get a list of currently installed webhooks.
14
+ #
15
+ # GET /api_v2/webhooks.json
16
+ def all
17
+ raw_response = get_request('webhooks')
18
+ parse_response(raw_response, :webhooks)
19
+ end
20
+
21
+ # CREATE
22
+ #
23
+ # When installing a webhook, specify an event you wish to hook into.
24
+ # Choose from: 'task_create', 'task_update', 'comment' or 'task_destroy'.
25
+ # To get activity for all 3 events, create an entry for each event.
26
+ #
27
+ # 'project_id' is optional; it only needs to be specified if you'd only like
28
+ # events on a specific project. Omitting 'project_id' results in notifications
29
+ # of activity on all your projects.
30
+ #
31
+ # PARAMS
32
+ # {
33
+ # 'project_id':1,
34
+ # 'target_url':'https://app.example.com/api/bugherd_sync/project/1/task_create',
35
+ # 'event':'task_create'
36
+ # }
37
+ #
38
+ def create(payload = {})
39
+ raw_response = post_request('webhooks', payload)
40
+ parse_response(raw_response, :webhook)
41
+ end
42
+
43
+ # DELETE
44
+ #
45
+ # DELETE /api_v2/webhooks/#{id}.json
46
+ def delete(webhook_id)
47
+ raw_response = delete_request("webhooks/#{webhook_id}")
48
+ parse_response(raw_response)
49
+ end
50
+
51
+ end
52
+ end # V2
53
+ end # Resources
54
+ end # BugherdClient
@@ -2,7 +2,7 @@ module BugherdClient
2
2
  module VERSION
3
3
  MAJOR = 0
4
4
  MINOR = 0
5
- PATCH = 6
5
+ PATCH = 8
6
6
 
7
7
  STRING = [MAJOR,MINOR,PATCH].join('.')
8
8
  end