tracker_api 1.11.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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