From 9f0746bbd8a85d28a86ebbb170c6c88d2c4ca9c2 Mon Sep 17 00:00:00 2001 From: Jason Atwood Date: Thu, 29 Dec 2016 15:41:57 -0500 Subject: [PATCH 1/4] Add endpoint to request story transitions --- README.md | 1 + lib/tracker_api.rb | 2 ++ .../endpoints/story_transitions.rb | 20 +++++++++++++++++++ lib/tracker_api/resources/story.rb | 13 ++++++++++++ lib/tracker_api/resources/story_transition.rb | 10 ++++++++++ test/story_test.rb | 14 +++++++++++++ 6 files changed, 60 insertions(+) create mode 100644 lib/tracker_api/endpoints/story_transitions.rb create mode 100644 lib/tracker_api/resources/story_transition.rb diff --git a/README.md b/README.md index 4e75714..2b4cb92 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ project.create_story(name: 'Destroy death star') # Crea story = project.story(847762630) # Find a story with the given ID story.activity # Get a list of all the activity performed on this story +story.story_transitions # Get a list of all the story transitions on this story story.name = 'Save the Ewoks' # Update a single story attribute story.attributes = { name: 'Save the Ewoks', description: '...' } # Update multiple story attributes diff --git a/lib/tracker_api.rb b/lib/tracker_api.rb index 35228ff..86fe10e 100644 --- a/lib/tracker_api.rb +++ b/lib/tracker_api.rb @@ -53,6 +53,7 @@ module Endpoints autoload :Comment, 'tracker_api/endpoints/comment' autoload :Webhook, 'tracker_api/endpoints/webhook' autoload :Webhooks, 'tracker_api/endpoints/webhooks' + autoload :StoryTransitions, 'tracker_api/endpoints/story_transitions' end module Resources @@ -79,5 +80,6 @@ module Shared autoload :TimeZone, 'tracker_api/resources/time_zone' autoload :Comment, 'tracker_api/resources/comment' autoload :Webhook, 'tracker_api/resources/webhook' + autoload :StoryTransition, 'tracker_api/resources/story_transition' end end diff --git a/lib/tracker_api/endpoints/story_transitions.rb b/lib/tracker_api/endpoints/story_transitions.rb new file mode 100644 index 0000000..4cbc5c4 --- /dev/null +++ b/lib/tracker_api/endpoints/story_transitions.rb @@ -0,0 +1,20 @@ +module TrackerApi + module Endpoints + class StoryTransitions + attr_accessor :client + + def initialize(client) + @client = client + end + + def get(project_id, story_id, params={}) + data = client.paginate("/projects/#{project_id}/stories/#{story_id}/transitions", params: params) + raise Errors::UnexpectedData, 'Array of story transitions expected' unless data.is_a? Array + + data.map do |transition| + Resources::StoryTransition.new(transition) + end + end + end + end +end \ No newline at end of file diff --git a/lib/tracker_api/resources/story.rb b/lib/tracker_api/resources/story.rb index a7058ec..07f78ab 100644 --- a/lib/tracker_api/resources/story.rb +++ b/lib/tracker_api/resources/story.rb @@ -34,6 +34,7 @@ class Story attribute :story_type, String # (feature, bug, chore, release) attribute :task_ids, [Integer] attribute :tasks, [Task] + attribute :transitions, [StoryTransition] attribute :updated_at, DateTime attribute :url, String @@ -121,6 +122,18 @@ def owners(params = {}) end end + # Provides a list of all the transitions of the story. + # + # @param [Hash] params + # @return [Array[StoryTransition]] + def story_transitions(params = {}) + if params.blank? && @transitions.present? + @transitions + else + @transitions = Endpoints::StoryTransitions.new(client).get(project_id, id, params) + end + end + # @param [Hash] params attributes to create the task with # @return [Task] newly created Task def create_task(params) diff --git a/lib/tracker_api/resources/story_transition.rb b/lib/tracker_api/resources/story_transition.rb new file mode 100644 index 0000000..889d896 --- /dev/null +++ b/lib/tracker_api/resources/story_transition.rb @@ -0,0 +1,10 @@ +module TrackerApi + module Resources + class StoryTransition + include Shared::Base + + attribute :state, String + attribute :occurred_at, DateTime + end + end +end diff --git a/test/story_test.rb b/test/story_test.rb index a4c8d52..60d0ce8 100644 --- a/test/story_test.rb +++ b/test/story_test.rb @@ -225,4 +225,18 @@ end end end + + describe '.story_transitions' do + it 'gets all story transitions with just project_id and story_id' do + VCR.use_cassette('get story transitions', record: :new_episodes) do + story = TrackerApi::Resources::Story.new( client: client, + project_id: project_id, + id: story_id) + + transitions = story.transitions + transition = transitions.first + transition.must_be_instance_of TrackerApi::Resources::StoryTransition + end + end + end end From 6fa5232eeaf7f0c68a977a3552de897bccb67378 Mon Sep 17 00:00:00 2001 From: Jason Atwood Date: Thu, 29 Dec 2016 15:42:22 -0500 Subject: [PATCH 2/4] Update error message --- lib/tracker_api/endpoints/story_owners.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tracker_api/endpoints/story_owners.rb b/lib/tracker_api/endpoints/story_owners.rb index 8679da8..b0a7d85 100644 --- a/lib/tracker_api/endpoints/story_owners.rb +++ b/lib/tracker_api/endpoints/story_owners.rb @@ -9,7 +9,7 @@ def initialize(client) def get(project_id, story_id, params={}) data = client.paginate("/projects/#{project_id}/stories/#{story_id}/owners", params: params) - raise Errors::UnexpectedData, 'Array of comments expected' unless data.is_a? Array + raise Errors::UnexpectedData, 'Array of story owners expected' unless data.is_a? Array data.map do |owner| Resources::Person.new({ story_id: story_id }.merge(owner)) From bea84d6291581679c105ddc87576d61fc495d688 Mon Sep 17 00:00:00 2001 From: Jason Atwood Date: Mon, 2 Jan 2017 17:23:41 -0500 Subject: [PATCH 3/4] Rename method to match attribute --- lib/tracker_api/resources/story.rb | 2 +- test/vcr/cassettes/get_story_transitions.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 test/vcr/cassettes/get_story_transitions.json diff --git a/lib/tracker_api/resources/story.rb b/lib/tracker_api/resources/story.rb index 07f78ab..565aab6 100644 --- a/lib/tracker_api/resources/story.rb +++ b/lib/tracker_api/resources/story.rb @@ -126,7 +126,7 @@ def owners(params = {}) # # @param [Hash] params # @return [Array[StoryTransition]] - def story_transitions(params = {}) + def transitions(params = {}) if params.blank? && @transitions.present? @transitions else diff --git a/test/vcr/cassettes/get_story_transitions.json b/test/vcr/cassettes/get_story_transitions.json new file mode 100644 index 0000000..c1d085b --- /dev/null +++ b/test/vcr/cassettes/get_story_transitions.json @@ -0,0 +1 @@ +{"http_interactions":[{"request":{"method":"get","uri":"https://www.pivotaltracker.com/services/v5/projects/1027488/stories/66728004/transitions","body":{"encoding":"US-ASCII","string":""},"headers":{"User-Agent":["Ruby/2.1.1 (x86_64-darwin12.0; ruby) TrackerApi/1.5.0 Faraday/0.9.2"],"X-TrackerToken":["d55c3bc1f74346b843ca84ba340b29bf"]}},"response":{"status":{"code":200,"message":null},"headers":{"Access-Control-Allow-Credentials":["false"],"Access-Control-Allow-Headers":["X-TrackerToken,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Tracker-Warn-Unless-Project-Version-Is"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Origin":["*"],"Cache-Control":["max-age=0, private, must-revalidate"],"Content-Type":["application/json; charset=utf-8"],"Date":["Mon, 02 Jan 2017 22:14:56 GMT"],"Etag":["\"d751713988987e9331980363e24189ce\""],"Server":["nginx + Phusion Passenger"],"Status":["200 OK"],"Strict-Transport-Security":["max-age=31536000; includeSubDomains; preload"],"X-Powered-By":["Phusion Passenger Enterprise"],"X-Rack-Cache":["miss"],"X-Request-Id":["378f3e29dde95b40f58282f630072f5e"],"X-Runtime":["0.042142"],"X-Tracker-Client-Pinger-Interval":["20"],"X-Tracker-Pagination-Limit":["100"],"X-Tracker-Pagination-Offset":["0"],"X-Tracker-Pagination-Returned":["0"],"X-Tracker-Pagination-Total":["0"],"X-Tracker-Project-Version":["156"],"X-Ua-Compatible":["IE=Edge,chrome=1"],"X-Vcap-Request-Id":["c8390582-7a35-455d-5fa6-95b7b59b3fc3"],"Content-Length":["2"],"Connection":["keep-alive"]},"body":{"encoding":"ASCII-8BIT","string":"[]"},"http_version":null},"recorded_at":"Mon, 02 Jan 2017 22:14:56 GMT"}],"recorded_with":"VCR 3.0.3"} \ No newline at end of file From 9e8664081fe14d1cc631d295adaaac7b3571e01d Mon Sep 17 00:00:00 2001 From: Forest Carlisle Date: Tue, 3 Jan 2017 15:51:50 -0800 Subject: [PATCH 4/4] Switch to using a story that had some transitions. * Had to create some transitions for the given story on the web site. * Updated the readme. --- README.md | 2 +- test/story_test.rb | 4 ++-- test/vcr/cassettes/get_story_transitions.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2b4cb92..b8ab299 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ project.create_story(name: 'Destroy death star') # Crea story = project.story(847762630) # Find a story with the given ID story.activity # Get a list of all the activity performed on this story -story.story_transitions # Get a list of all the story transitions on this story +story.transitions # Get a list of all the story transitions on this story story.name = 'Save the Ewoks' # Update a single story attribute story.attributes = { name: 'Save the Ewoks', description: '...' } # Update multiple story attributes diff --git a/test/story_test.rb b/test/story_test.rb index 60d0ce8..8a1f550 100644 --- a/test/story_test.rb +++ b/test/story_test.rb @@ -226,12 +226,12 @@ end end - describe '.story_transitions' do + describe '.transitions' do it 'gets all story transitions with just project_id and story_id' do VCR.use_cassette('get story transitions', record: :new_episodes) do story = TrackerApi::Resources::Story.new( client: client, project_id: project_id, - id: story_id) + id: another_story_id) transitions = story.transitions transition = transitions.first diff --git a/test/vcr/cassettes/get_story_transitions.json b/test/vcr/cassettes/get_story_transitions.json index c1d085b..54a8459 100644 --- a/test/vcr/cassettes/get_story_transitions.json +++ b/test/vcr/cassettes/get_story_transitions.json @@ -1 +1 @@ -{"http_interactions":[{"request":{"method":"get","uri":"https://www.pivotaltracker.com/services/v5/projects/1027488/stories/66728004/transitions","body":{"encoding":"US-ASCII","string":""},"headers":{"User-Agent":["Ruby/2.1.1 (x86_64-darwin12.0; ruby) TrackerApi/1.5.0 Faraday/0.9.2"],"X-TrackerToken":["d55c3bc1f74346b843ca84ba340b29bf"]}},"response":{"status":{"code":200,"message":null},"headers":{"Access-Control-Allow-Credentials":["false"],"Access-Control-Allow-Headers":["X-TrackerToken,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Tracker-Warn-Unless-Project-Version-Is"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Origin":["*"],"Cache-Control":["max-age=0, private, must-revalidate"],"Content-Type":["application/json; charset=utf-8"],"Date":["Mon, 02 Jan 2017 22:14:56 GMT"],"Etag":["\"d751713988987e9331980363e24189ce\""],"Server":["nginx + Phusion Passenger"],"Status":["200 OK"],"Strict-Transport-Security":["max-age=31536000; includeSubDomains; preload"],"X-Powered-By":["Phusion Passenger Enterprise"],"X-Rack-Cache":["miss"],"X-Request-Id":["378f3e29dde95b40f58282f630072f5e"],"X-Runtime":["0.042142"],"X-Tracker-Client-Pinger-Interval":["20"],"X-Tracker-Pagination-Limit":["100"],"X-Tracker-Pagination-Offset":["0"],"X-Tracker-Pagination-Returned":["0"],"X-Tracker-Pagination-Total":["0"],"X-Tracker-Project-Version":["156"],"X-Ua-Compatible":["IE=Edge,chrome=1"],"X-Vcap-Request-Id":["c8390582-7a35-455d-5fa6-95b7b59b3fc3"],"Content-Length":["2"],"Connection":["keep-alive"]},"body":{"encoding":"ASCII-8BIT","string":"[]"},"http_version":null},"recorded_at":"Mon, 02 Jan 2017 22:14:56 GMT"}],"recorded_with":"VCR 3.0.3"} \ No newline at end of file +{"http_interactions":[{"request":{"method":"get","uri":"https://www.pivotaltracker.com/services/v5/projects/1027488/stories/66728000/transitions","body":{"encoding":"US-ASCII","string":""},"headers":{"User-Agent":["Ruby/2.3.1 (x86_64-darwin15; ruby) TrackerApi/1.5.0 Faraday/0.9.2"],"X-TrackerToken":["d55c3bc1f74346b843ca84ba340b29bf"]}},"response":{"status":{"code":200,"message":null},"headers":{"Access-Control-Allow-Credentials":["false"],"Access-Control-Allow-Headers":["X-TrackerToken,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Tracker-Warn-Unless-Project-Version-Is"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Origin":["*"],"Cache-Control":["max-age=0, private, must-revalidate"],"Content-Type":["application/json; charset=utf-8"],"Date":["Tue, 03 Jan 2017 23:50:01 GMT"],"Etag":["\"967a44e1aeaba9aa5d3432b3ac55f0f6\""],"Server":["nginx + Phusion Passenger"],"Status":["200 OK"],"Strict-Transport-Security":["max-age=31536000; includeSubDomains; preload"],"X-Powered-By":["Phusion Passenger Enterprise"],"X-Rack-Cache":["miss"],"X-Request-Id":["875c2082f7e398467f4ae81092835c33"],"X-Runtime":["0.034241"],"X-Tracker-Client-Pinger-Interval":["20"],"X-Tracker-Pagination-Limit":["100"],"X-Tracker-Pagination-Offset":["0"],"X-Tracker-Pagination-Returned":["2"],"X-Tracker-Pagination-Total":["2"],"X-Tracker-Project-Version":["158"],"X-Ua-Compatible":["IE=Edge,chrome=1"],"X-Vcap-Request-Id":["18224844-f694-42c2-4596-825cb100f788"],"Content-Length":["347"],"Connection":["keep-alive"]},"body":{"encoding":"ASCII-8BIT","string":"[{\"kind\":\"story_transition\",\"state\":\"accepted\",\"story_id\":66728000,\"project_id\":1027488,\"project_version\":157,\"occurred_at\":\"2017-01-03T23:44:24Z\",\"performed_by_id\":1266314},{\"kind\":\"story_transition\",\"state\":\"rejected\",\"story_id\":66728000,\"project_id\":1027488,\"project_version\":158,\"occurred_at\":\"2017-01-03T23:49:51Z\",\"performed_by_id\":1266314}]"},"http_version":null},"recorded_at":"Tue, 03 Jan 2017 23:50:01 GMT"}],"recorded_with":"VCR 2.9.3"} \ No newline at end of file