tracker_api 1.11.0 → 1.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ruby-tests.yml +43 -0
  3. data/Gemfile +0 -3
  4. data/LICENSE.txt +17 -18
  5. data/README.md +13 -7
  6. data/gemfiles/faraday-1.gemfile +5 -0
  7. data/gemfiles/faraday-2.gemfile +5 -0
  8. data/lib/tracker_api/client.rb +1 -1
  9. data/lib/tracker_api/endpoints/attachment.rb +3 -1
  10. data/lib/tracker_api/endpoints/comment.rb +15 -5
  11. data/lib/tracker_api/endpoints/comments.rb +10 -5
  12. data/lib/tracker_api/endpoints/review.rb +21 -0
  13. data/lib/tracker_api/file_utility.rb +1 -1
  14. data/lib/tracker_api/logger.rb +1 -1
  15. data/lib/tracker_api/resources/comment.rb +2 -2
  16. data/lib/tracker_api/resources/epic.rb +10 -1
  17. data/lib/tracker_api/resources/pull_request.rb +22 -0
  18. data/lib/tracker_api/resources/review.rb +17 -1
  19. data/lib/tracker_api/resources/story.rb +4 -3
  20. data/lib/tracker_api/version.rb +1 -1
  21. data/lib/tracker_api.rb +4 -2
  22. data/test/comment_test.rb +94 -25
  23. data/test/iteration_test.rb +3 -3
  24. data/test/minitest_helper.rb +2 -2
  25. data/test/review_test.rb +27 -0
  26. data/test/story_test.rb +13 -1
  27. data/test/vcr/cassettes/create_epic_attachments.json +1 -0
  28. data/test/vcr/cassettes/create_epic_comment.json +1 -0
  29. data/test/vcr/cassettes/create_epic_comment_with_attachment.json +1 -0
  30. data/test/vcr/cassettes/create_story_attachments.json +1 -0
  31. data/test/vcr/cassettes/create_story_comment.json +1 -1
  32. data/test/vcr/cassettes/create_story_comment_with_attachment.json +1 -0
  33. data/test/vcr/cassettes/delete_epic_attachments.json +1 -0
  34. data/test/vcr/cassettes/delete_epic_comment.json +1 -0
  35. data/test/vcr/cassettes/delete_story_attachments.json +1 -0
  36. data/test/vcr/cassettes/delete_story_comment.json +1 -0
  37. data/test/vcr/cassettes/get_epic.json +1 -0
  38. data/test/vcr/cassettes/get_epic_comments.json +1 -0
  39. data/test/vcr/cassettes/get_story_with_pull_requests.json +1 -0
  40. data/test/vcr/cassettes/save_epic_comment.json +1 -0
  41. data/test/vcr/cassettes/save_review.json +1 -0
  42. data/test/vcr/cassettes/save_story_comment.json +1 -0
  43. data/tracker_api.gemspec +7 -7
  44. metadata +61 -20
  45. data/.travis.yml +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: cce8ed0f32ae28c44915d1a2aa0dff3f7deb44f9
4
- data.tar.gz: 6478d86c0e8e8e826e0ffd50b8111758f0dec9c0
2
+ SHA256:
3
+ metadata.gz: 849c1d3fe22b5b812ed7144d3d0703a7a6f3701d575f5d794cf9f9dc8caf6643
4
+ data.tar.gz: d142dccb5a2eec0474e54262f351e4ea148651dd7c0c7a28fcb93acdbb9f3d25
5
5
  SHA512:
6
- metadata.gz: 34b10827d2868cf6e0de4039ef23444b412fcb5d162e6fca2a20258f22d3ceede1e45cb4f7e829cb57ccd8a66a3506144e53eed8f7ae6954b2d2196c6244e0f1
7
- data.tar.gz: 69eb1bbad1ea7a6ef35b84e36c9b856ebc300eda60369769c242a9ec77fd5cf3c436c7280101341f657d46beab1fc382e16bbb43c074bcb6b89c97b74d71105b
6
+ metadata.gz: 62a6cab610b4c3e4b43ff6b7ca007e477e0478e6c1e3821b2d49a1052a830d030dbf7bfcebb91158a2493cc589e8d7ca0155f3621a0e52119ff40fba560a243a
7
+ data.tar.gz: a030d836b14d017f57c2eaf91f12cb7b9202c23a0cabd6e2e08b425c5185f10cb477b1ec3e598c19cdf63889dcaf23ae5c3ede9dfdc28adc562aac4f9785ad17
@@ -0,0 +1,43 @@
1
+ name: Ruby Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
+
9
+ jobs:
10
+ test:
11
+
12
+ name: Specs - Ruby ${{ matrix.ruby-version }} ${{matrix.gemfile}}
13
+ runs-on: ubuntu-latest
14
+ env:
15
+ CC_TEST_REPORTER_ID: 2a6849be8214739deef0090b810b945ce9a550a4d8279d242cb03242d1ad53c5
16
+ BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
17
+
18
+ strategy:
19
+ matrix:
20
+ gemfile:
21
+ - faraday-1
22
+ - faraday-2
23
+ ruby-version:
24
+ - "3.1"
25
+ - "3.0"
26
+ - "2.7"
27
+ - "2.6"
28
+ - jruby
29
+ - truffleruby
30
+
31
+ steps:
32
+ - uses: actions/checkout@v2
33
+ - name: Set up Ruby ${{ matrix.ruby-version }}
34
+ uses: ruby/setup-ruby@v1
35
+ with:
36
+ ruby-version: ${{ matrix.ruby-version }}
37
+ - name: Install dependencies
38
+ run: bundle install
39
+ - name: Run tests
40
+ run: bundle exec rake test
41
+ - name: Upload Coverage
42
+ uses: paambaati/codeclimate-action@v3.0.0
43
+ if: matrix.ruby-version == '3.1' && matrix.gemfile == 'faraday-2'
data/Gemfile CHANGED
@@ -2,6 +2,3 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in tracker_api.gemspec
4
4
  gemspec
5
-
6
- gem 'coveralls', group: :test, require: false
7
-
data/LICENSE.txt CHANGED
@@ -1,22 +1,21 @@
1
- Copyright (c) 2014 Dash of Code
2
-
3
1
  MIT License
4
2
 
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
3
+ Copyright (c) [2021] [ProductPlan]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
12
11
 
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
15
14
 
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -1,17 +1,19 @@
1
1
  # TrackerApi
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/tracker_api.png)](http://badge.fury.io/rb/tracker_api)
4
- [![Build Status](https://travis-ci.org/dashofcode/tracker_api.png?branch=master)](https://travis-ci.org/dashofcode/tracker_api)
5
- [![Code Climate](https://codeclimate.com/github/dashofcode/tracker_api.png)](https://codeclimate.com/github/dashofcode/tracker_api)
6
- [![Coverage Status](https://coveralls.io/repos/dashofcode/tracker_api/badge.png?branch=master)](https://coveralls.io/r/dashofcode/tracker_api?branch=master)
7
- [![Dependency Status](https://gemnasium.com/dashofcode/tracker_api.png)](https://gemnasium.com/dashofcode/tracker_api)
3
+ [![Gem Version](https://badge.fury.io/rb/tracker_api.svg)](http://badge.fury.io/rb/tracker_api)
4
+ [![Build Status](https://github.com/ProductPlan/tracker_api/actions/workflows/ruby-tests.yml/badge.svg?branch=master)](https://github.com/ProductPlan/tracker_api/actions)
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/c4602f519cd748d53492/maintainability)](https://codeclimate.com/github/ProductPlan/tracker_api/maintainability)
6
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/c4602f519cd748d53492/test_coverage)](https://codeclimate.com/github/ProductPlan/tracker_api/test_coverage)
8
7
 
9
8
  This gem allows you to easily use the [Pivotal Tracker v5 API](https://www.pivotaltracker.com/help/api/rest/v5).
10
9
 
11
10
  It’s powered by [Faraday](https://github.com/lostisland/faraday) and [Virtus](https://github.com/solnic/virtus).
12
11
 
13
- ## Demonstration
14
- [Dash of Agile](https://www.dashofagile.com) uses `tracker_api` to create agile dashboards from Pivotal Tracker projects.
12
+ ## Compatibility
13
+
14
+ This gem is tested against the following officially supported Ruby versions:
15
+ - Minimum Ruby Version: 2.6.x
16
+ - Latest Ruby Supported: 3.1.x
15
17
 
16
18
  ## Installation
17
19
 
@@ -86,6 +88,10 @@ task = story.tasks.first # Get
86
88
  task.complete = true
87
89
  task.save # Mark a task complete
88
90
 
91
+ review = story.reviews.first # Mark a review as complete
92
+ review.status = 'pass'
93
+ review.save
94
+
89
95
  epics = project.epics # Get all epics for a project
90
96
  epic = epics.first
91
97
  label = epic.label # Get an epic's label
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'faraday', '~> 1.10'
4
+
5
+ gemspec path: '../'
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'faraday', '~> 2.2'
4
+
5
+ gemspec path: '../'
@@ -25,7 +25,7 @@ module TrackerApi
25
25
  @url = Addressable::URI.parse(url).to_s
26
26
  @api_version = options.fetch(:api_version, '/services/v5')
27
27
  @logger = options.fetch(:logger, ::Logger.new(nil))
28
- adapter = options.fetch(:adapter) { defined?(JRUBY_VERSION) ? :net_http : :excon }
28
+ adapter = options.fetch(:adapter, :net_http)
29
29
  connection_options = options.fetch(:connection_options, { ssl: { verify: true } })
30
30
  @auto_paginate = options.fetch(:auto_paginate, true)
31
31
  @token = options[:token]
@@ -19,7 +19,9 @@ module TrackerApi
19
19
  # end
20
20
 
21
21
  def get(comment)
22
- data = client.get("/projects/#{comment.project_id}/stories/#{comment.story_id}/comments/#{comment.id}?fields=file_attachments").body["file_attachments"]
22
+ comment_target_slug = !comment.story_id.nil? ? "stories/#{comment.story_id}" : "epics/#{comment.epic_id}"
23
+
24
+ data = client.get("/projects/#{comment.project_id}/#{comment_target_slug}/comments/#{comment.id}?fields=file_attachments").body["file_attachments"]
23
25
  raise Errors::UnexpectedData, 'Array of file attachments expected' unless data.is_a? Array
24
26
 
25
27
  data.map do |file_attachment|
@@ -7,16 +7,24 @@ module TrackerApi
7
7
  @client = client
8
8
  end
9
9
 
10
- def create(project_id, story_id, params={})
11
- data = client.post("/projects/#{project_id}/stories/#{story_id}/comments", params: params).body
10
+ def create(project_id, story_id: nil, epic_id: nil, params: {})
11
+ raise ArgumentError, 'One of story id or epic id must be provided.' if story_id.nil? && epic_id.nil?
12
+
13
+ comment_target_slug = !story_id.nil? ? "stories/#{story_id}" : "epics/#{epic_id}"
14
+
15
+ data = client.post("/projects/#{project_id}/#{comment_target_slug}/comments", params: params).body
12
16
  Resources::Comment.new({ client: client, project_id: project_id }.merge(data))
13
17
  end
14
18
 
15
19
  def update(comment, params={})
16
20
  raise ArgumentError, 'Valid comment required to update.' unless comment.instance_of?(Resources::Comment)
17
21
 
18
- path = "/projects/#{comment.project_id}/stories/#{comment.story_id}/comments/#{comment.id}"
19
- path += "?fields=:default,file_attachments" if params.represented.file_attachment_ids_to_add.present? || params.represented.file_attachment_ids_to_remove.present?
22
+ comment_target_slug = !comment.story_id.nil? ? "stories/#{comment.story_id}" : "epics/#{comment.epic_id}"
23
+
24
+ path = "/projects/#{comment.project_id}/#{comment_target_slug}/comments/#{comment.id}"
25
+ if params.represented.file_attachment_ids_to_add.present? || params.represented.file_attachment_ids_to_remove.present?
26
+ path += "?fields=:default,file_attachments"
27
+ end
20
28
  data = client.put(path, params: params).body
21
29
 
22
30
  comment.attributes = data
@@ -27,7 +35,9 @@ module TrackerApi
27
35
  def delete(comment)
28
36
  raise ArgumentError, 'Valid comment required to update.' unless comment.instance_of?(Resources::Comment)
29
37
 
30
- client.delete("/projects/#{comment.project_id}/stories/#{comment.story_id}/comments/#{comment.id}").body
38
+ comment_target_slug = !comment.story_id.nil? ? "stories/#{comment.story_id}" : "epics/#{comment.epic_id}"
39
+
40
+ client.delete("/projects/#{comment.project_id}/#{comment_target_slug}/comments/#{comment.id}").body
31
41
  end
32
42
  end
33
43
  end
@@ -7,14 +7,19 @@ module TrackerApi
7
7
  @client = client
8
8
  end
9
9
 
10
- def get(project_id, story_id, params={})
11
- data = client.paginate("/projects/#{project_id}/stories/#{story_id}/comments", params: params)
10
+ def get(project_id, story_id: nil, epic_id: nil, params: {})
11
+ raise ArgumentError, 'One of story id or epic id must be provided.' if story_id.nil? && epic_id.nil?
12
+
13
+ comment_target_slug = !story_id.nil? ? "stories/#{story_id}" : "epics/#{epic_id}"
14
+
15
+ data = client.paginate("/projects/#{project_id}/#{comment_target_slug}/comments", params: params)
12
16
  raise Errors::UnexpectedData, 'Array of comments expected' unless data.is_a? Array
13
17
 
14
18
  data.map do |comment|
15
- Resources::Comment.new({ client: client,
16
- project_id: project_id,
17
- story_id: story_id }.merge(comment))
19
+ Resources::Comment.new({
20
+ client: client,
21
+ project_id: project_id
22
+ }.merge(comment))
18
23
  end
19
24
  end
20
25
  end
@@ -0,0 +1,21 @@
1
+ module TrackerApi
2
+ module Endpoints
3
+ class Review
4
+ attr_accessor :client
5
+
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ def update(review, params = {})
11
+ raise ArgumentError, 'Valid review required to update.' unless review.instance_of?(Resources::Review)
12
+
13
+ data = client.put("/projects/#{review.project_id}/stories/#{review.story_id}/reviews/#{review.id}", params: params).body
14
+
15
+ review.attributes = data
16
+ review.clean!
17
+ review
18
+ end
19
+ end
20
+ end
21
+ end
@@ -2,7 +2,7 @@ module TrackerApi
2
2
  class FileUtility
3
3
  class << self
4
4
  def get_file_upload(file)
5
- mime_type = MimeMagic.by_path(file)
5
+ mime_type = MiniMime.lookup_by_filename(file)
6
6
  { :file => Faraday::UploadIO.new(file, mime_type) }
7
7
  end
8
8
 
@@ -1,5 +1,5 @@
1
1
  module TrackerApi
2
- class Logger < Faraday::Response::Middleware
2
+ class Logger < Faraday::Middleware
3
3
  extend Forwardable
4
4
 
5
5
  def initialize(app, logger = nil)
@@ -32,13 +32,13 @@ module TrackerApi
32
32
  end
33
33
 
34
34
  def save
35
- raise ArgumentError, 'Cannot update a comment with an unknown story_id.' if story_id.nil?
35
+ raise ArgumentError, 'Cannot update a comment with an unknown story_id or epic_id.' if story_id.nil? && epic_id.nil?
36
36
 
37
37
  Endpoints::Comment.new(client).update(self, UpdateRepresenter.new(Comment.new(self.dirty_attributes)))
38
38
  end
39
39
 
40
40
  def delete
41
- raise ArgumentError, 'Cannot delete a comment with an unknown story_id.' if story_id.nil?
41
+ raise ArgumentError, 'Cannot delete a comment with an unknown story_id or epic_id.' if story_id.nil? && epic_id.nil?
42
42
 
43
43
  Endpoints::Comment.new(client).delete(self)
44
44
  end
@@ -35,11 +35,20 @@ module TrackerApi
35
35
  Endpoints::Epic.new(client).update(self, UpdateRepresenter.new(self))
36
36
  end
37
37
 
38
+ # Provides a list of all the comments on the epic.
39
+ def comments(reload: false)
40
+ if !reload && @comments.present?
41
+ @comments
42
+ else
43
+ @comments = Endpoints::Comments.new(client).get(project_id, epic_id: id)
44
+ end
45
+ end
46
+
38
47
  # @param [Hash] params attributes to create the comment with
39
48
  # @return [Comment] newly created Comment
40
49
  def create_comment(params)
41
50
  files = params.delete(:files)
42
- comment = Endpoints::Comment.new(client).create(project_id, id, params)
51
+ comment = Endpoints::Comment.new(client).create(project_id, epic_id: id, params: params)
43
52
  comment.create_attachments(files: files) if files.present?
44
53
  comment
45
54
  end
@@ -0,0 +1,22 @@
1
+ module TrackerApi
2
+ module Resources
3
+ class PullRequest
4
+ include Shared::Base
5
+
6
+ attribute :client
7
+
8
+ attribute :id, Integer
9
+ attribute :story_id, Integer
10
+ attribute :epic_id, Integer
11
+ attribute :owner, String
12
+ attribute :repo, String
13
+ attribute :number, Integer
14
+ attribute :host_url, String
15
+ attribute :original_url, String
16
+ attribute :status, String
17
+ attribute :created_at, DateTime
18
+ attribute :updated_at, DateTime
19
+ attribute :kind, String
20
+ end
21
+ end
22
+ end
@@ -7,6 +7,7 @@ module TrackerApi
7
7
 
8
8
  attribute :id, Integer
9
9
  attribute :story_id, Integer
10
+ attribute :project_id, Integer
10
11
  attribute :review_type_id, Integer
11
12
  attribute :reviewer_id, Integer
12
13
  attribute :status, String # (unstarted, in_review, pass, revise)
@@ -14,6 +15,21 @@ module TrackerApi
14
15
  attribute :updated_at, DateTime
15
16
  attribute :kind, String
16
17
  attribute :review_type, ReviewType
18
+
19
+ class UpdateRepresenter < Representable::Decorator
20
+ include Representable::JSON
21
+
22
+ property :id
23
+ property :review_type_id
24
+ property :reviewer_id
25
+ property :status
26
+ end
27
+
28
+ def save
29
+ raise ArgumentError, 'Cannot update a review with an unknown story_id.' if story_id.nil?
30
+
31
+ Endpoints::Review.new(client).update(self, UpdateRepresenter.new(Review.new(dirty_attributes)))
32
+ end
17
33
  end
18
34
  end
19
- end
35
+ end
@@ -30,6 +30,7 @@ module TrackerApi
30
30
  attribute :owners, [Person]
31
31
  attribute :planned_iteration_number, Integer
32
32
  attribute :project_id, Integer
33
+ attribute :pull_requests, [PullRequest]
33
34
  attribute :requested_by, Person
34
35
  attribute :requested_by_id, Integer
35
36
  attribute :reviews, [Review]
@@ -101,7 +102,7 @@ module TrackerApi
101
102
  #
102
103
  # @param [Person|Fixnum] owner
103
104
  def add_owner(owner)
104
- owner_id = if owner.kind_of?(Fixnum)
105
+ owner_id = if owner.kind_of?(Integer)
105
106
  owner_id = owner
106
107
  else
107
108
  raise ArgumentError, 'Valid Person expected.' unless owner.instance_of?(Resources::Person)
@@ -132,7 +133,7 @@ module TrackerApi
132
133
  if !reload && @comments.present?
133
134
  @comments
134
135
  else
135
- @comments = Endpoints::Comments.new(client).get(project_id, id)
136
+ @comments = Endpoints::Comments.new(client).get(project_id, story_id: id)
136
137
  end
137
138
  end
138
139
 
@@ -193,7 +194,7 @@ module TrackerApi
193
194
  # @return [Comment] newly created Comment
194
195
  def create_comment(params)
195
196
  files = params.delete(:files)
196
- comment = Endpoints::Comment.new(client).create(project_id, id, params)
197
+ comment = Endpoints::Comment.new(client).create(project_id, story_id: id, params: params)
197
198
  comment.create_attachments(files: files) if files.present?
198
199
  comment
199
200
  end
@@ -1,3 +1,3 @@
1
1
  module TrackerApi
2
- VERSION = '1.11.0'
2
+ VERSION = '1.14.0'
3
3
  end
data/lib/tracker_api.rb CHANGED
@@ -2,9 +2,9 @@ require 'tracker_api/version'
2
2
 
3
3
  # dependencies
4
4
  require 'faraday'
5
- require 'faraday_middleware'
5
+ require 'faraday/multipart'
6
6
  require 'pathname'
7
- require 'mimemagic'
7
+ require 'mini_mime'
8
8
 
9
9
  if defined?(ActiveSupport)
10
10
  require 'active_support/core_ext/object/blank'
@@ -66,6 +66,7 @@ module TrackerApi
66
66
  autoload :Attachments, 'tracker_api/endpoints/attachments'
67
67
  autoload :Releases, 'tracker_api/endpoints/releases'
68
68
  autoload :Release, 'tracker_api/endpoints/release'
69
+ autoload :Review, 'tracker_api/endpoints/review'
69
70
  autoload :Reviews, 'tracker_api/endpoints/reviews'
70
71
  end
71
72
 
@@ -89,6 +90,7 @@ module TrackerApi
89
90
  autoload :PrimaryResource, 'tracker_api/resources/primary_resource'
90
91
  autoload :Project, 'tracker_api/resources/project'
91
92
  autoload :ProjectMembership, 'tracker_api/resources/project_membership'
93
+ autoload :PullRequest, 'tracker_api/resources/pull_request'
92
94
  autoload :Workspace, 'tracker_api/resources/workspace'
93
95
  autoload :SearchResultContainer, 'tracker_api/resources/search_result_container'
94
96
  autoload :StoriesSearchResult, 'tracker_api/resources/stories_search_result'
data/test/comment_test.rb CHANGED
@@ -7,13 +7,17 @@ describe TrackerApi::Resources::Comment do
7
7
  let(:project) { VCR.use_cassette('get project') { client.project(project_id) } }
8
8
  let(:story_id) { '66728004' }
9
9
  let(:story) { VCR.use_cassette('get story') { project.story(story_id) } }
10
- let(:comments) { VCR.use_cassette('get comments') { story.comments } }
11
- let(:existing_comment) { comments.first }
10
+ let(:story_comments) { VCR.use_cassette('get story comments') { story.comments } }
11
+ let(:epic_id) { '4737194' }
12
+ let(:epic) { VCR.use_cassette('get epic') { project.epic(epic_id) } }
13
+ let(:epic_comments) { VCR.use_cassette('get epic comments') { epic.comments } }
14
+ let(:existing_story_comment) { story_comments.first }
15
+ let(:existing_epic_comment) { epic_comments.first }
12
16
 
13
17
  it 'can create a comment given a story' do
14
18
  text = "Test creating a comment"
15
19
  comment = nil
16
- VCR.use_cassette('create comment', record: :new_episodes) do
20
+ VCR.use_cassette('create story comment', record: :new_episodes) do
17
21
  comment = story.create_comment(text: text)
18
22
  end
19
23
 
@@ -21,11 +25,22 @@ describe TrackerApi::Resources::Comment do
21
25
  _(comment.clean?).must_equal true
22
26
  end
23
27
 
24
- it 'can create a comment with file attachment' do
28
+ it 'can create a comment given an epic' do
29
+ text = "Test creating a comment"
30
+ comment = nil
31
+ VCR.use_cassette('create epic comment', record: :new_episodes) do
32
+ comment = epic.create_comment(text: text)
33
+ end
34
+
35
+ _(comment.text).must_equal text
36
+ _(comment.clean?).must_equal true
37
+ end
38
+
39
+ it 'can create a story comment with file attachment' do
25
40
  text = "Test creating a comment"
26
41
  comment = nil
27
42
  files = [File.expand_path('../Gemfile', File.dirname(__FILE__))]
28
- VCR.use_cassette('create comment with attachment', record: :new_episodes) do
43
+ VCR.use_cassette('create story comment with attachment', record: :new_episodes) do
29
44
  comment = story.create_comment(text: text, files: files)
30
45
  end
31
46
  _(comment.text).must_equal text
@@ -33,39 +48,82 @@ describe TrackerApi::Resources::Comment do
33
48
  _(comment.clean?).must_equal true
34
49
  end
35
50
 
36
- it 'can update an existing comment' do
37
- new_text = "#{existing_comment.text}+"
38
- existing_comment.text = new_text
51
+ it 'can create an epic comment with file attachment' do
52
+ text = "Test creating a comment"
53
+ comment = nil
54
+ files = [File.expand_path('../Gemfile', File.dirname(__FILE__))]
55
+ VCR.use_cassette('create epic comment with attachment', record: :new_episodes) do
56
+ comment = epic.create_comment(text: text, files: files)
57
+ end
58
+ _(comment.text).must_equal text
59
+ _(comment.attachments.size).must_equal 1
60
+ _(comment.clean?).must_equal true
61
+ end
62
+
63
+ it 'can update an existing story comment' do
64
+ new_text = "#{existing_story_comment.text}+"
65
+ existing_story_comment.text = new_text
39
66
 
40
- VCR.use_cassette('save comment', record: :new_episodes) do
41
- existing_comment.save
67
+ VCR.use_cassette('save story comment', record: :new_episodes) do
68
+ existing_story_comment.save
42
69
  end
43
70
 
44
- _(existing_comment.text).must_equal new_text
45
- _(existing_comment.clean?).must_equal true
71
+ _(existing_story_comment.text).must_equal new_text
72
+ _(existing_story_comment.clean?).must_equal true
46
73
  end
47
74
 
48
- it 'can create attachments in a comment' do
75
+ it 'can update an existing epic comment' do
76
+ new_text = "#{existing_epic_comment.text}+"
77
+ existing_epic_comment.text = new_text
78
+
79
+ VCR.use_cassette('save epic comment', record: :new_episodes) do
80
+ existing_epic_comment.save
81
+ end
82
+
83
+ _(existing_epic_comment.text).must_equal new_text
84
+ _(existing_epic_comment.clean?).must_equal true
85
+ end
86
+
87
+ it 'can create attachments in a story comment' do
88
+ files = [File.expand_path('../Gemfile', File.dirname(__FILE__))]
89
+ VCR.use_cassette('create story attachments', record: :new_episodes) do
90
+ existing_story_comment.create_attachments(files: files)
91
+ assert existing_story_comment.attachments.size > 0
92
+ _(existing_story_comment.clean?).must_equal true
93
+ end
94
+ end
95
+
96
+ it 'can create attachments in an epic comment' do
97
+ files = [File.expand_path('../Gemfile', File.dirname(__FILE__))]
98
+ VCR.use_cassette('create epic attachments', record: :new_episodes) do
99
+ existing_epic_comment.create_attachments(files: files)
100
+ assert existing_epic_comment.attachments.size > 0
101
+ _(existing_epic_comment.clean?).must_equal true
102
+ end
103
+ end
104
+
105
+ it 'can delete attachments in a story comment' do
49
106
  files = [File.expand_path('../Gemfile', File.dirname(__FILE__))]
50
- VCR.use_cassette('create attachments', record: :new_episodes) do
51
- existing_comment.create_attachments(files: files)
52
- _(existing_comment.attachments.size).must_equal 1
53
- _(existing_comment.clean?).must_equal true
107
+ VCR.use_cassette('delete story attachments', record: :new_episodes) do
108
+ existing_story_comment.create_attachments(files: files)
109
+ assert existing_story_comment.attachments.size > 0
110
+ existing_story_comment.delete_attachments
111
+ _(existing_story_comment.attachments.size).must_equal 0
54
112
  end
55
113
  end
56
114
 
57
- it 'can delete attachments in a comment' do
115
+ it 'can delete attachments in an epic comment' do
58
116
  files = [File.expand_path('../Gemfile', File.dirname(__FILE__))]
59
- VCR.use_cassette('delete attachments', record: :new_episodes) do
60
- existing_comment.create_attachments(files: files)
61
- _(existing_comment.attachments.size).must_equal 1
62
- existing_comment.delete_attachments
63
- _(existing_comment.attachments.size).must_equal 0
117
+ VCR.use_cassette('delete epic attachments', record: :new_episodes) do
118
+ existing_epic_comment.create_attachments(files: files)
119
+ assert existing_epic_comment.attachments.size > 0
120
+ existing_epic_comment.delete_attachments
121
+ _(existing_epic_comment.attachments.size).must_equal 0
64
122
  end
65
123
  end
66
124
 
67
- it 'can delete a comment' do
68
- VCR.use_cassette('delete comment', record: :new_episodes) do
125
+ it 'can delete a story comment' do
126
+ VCR.use_cassette('delete story comment', record: :new_episodes) do
69
127
  current_story = project.story(story_id)
70
128
  new_comment_id = current_story.create_comment(text: "test comment").id
71
129
  _(current_story.comments.last.id).must_equal new_comment_id
@@ -74,4 +132,15 @@ describe TrackerApi::Resources::Comment do
74
132
  _(current_story.comments.last.id).wont_equal new_comment_id
75
133
  end
76
134
  end
135
+
136
+ it 'can delete an epic comment' do
137
+ VCR.use_cassette('delete epic comment', record: :new_episodes) do
138
+ current_epic = project.epic(epic_id)
139
+ new_comment_id = current_epic.create_comment(text: "test comment").id
140
+ _(current_epic.comments.last.id).must_equal new_comment_id
141
+ current_epic.comments.last.delete
142
+ current_epic = project.epic(epic_id)
143
+ _(current_epic.comments.last.id).wont_equal new_comment_id
144
+ end
145
+ end
77
146
  end
@@ -12,9 +12,9 @@ describe TrackerApi::Resources::Iteration do
12
12
  VCR.use_cassette('get cycle time details', record: :new_episodes) do
13
13
  cycle_time_details = iteration.cycle_time_details
14
14
 
15
- cycle_time_details.wont_be_empty
15
+ _(cycle_time_details).wont_be_empty
16
16
  cycle_time_detail = cycle_time_details.first
17
- cycle_time_detail.must_be_instance_of TrackerApi::Resources::CycleTimeDetails
17
+ _(cycle_time_detail).must_be_instance_of TrackerApi::Resources::CycleTimeDetails
18
18
  end
19
19
  end
20
20
  end
@@ -24,7 +24,7 @@ describe TrackerApi::Resources::Iteration do
24
24
  VCR.use_cassette('get daily history container', record: :new_episodes) do
25
25
  daily_history_container = iteration.get_history
26
26
 
27
- daily_history_container.must_be_instance_of TrackerApi::Resources::DailyHistoryContainer
27
+ _(daily_history_container).must_be_instance_of TrackerApi::Resources::DailyHistoryContainer
28
28
  end
29
29
  end
30
30
  end