diff --git a/README.md b/README.md index 4e75714..b8ab299 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.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_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)) 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..565aab6 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 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..8a1f550 100644 --- a/test/story_test.rb +++ b/test/story_test.rb @@ -225,4 +225,18 @@ end end end + + 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: another_story_id) + + transitions = story.transitions + transition = transitions.first + transition.must_be_instance_of TrackerApi::Resources::StoryTransition + end + end + end end diff --git a/test/vcr/cassettes/get_story_transitions.json b/test/vcr/cassettes/get_story_transitions.json new file mode 100644 index 0000000..54a8459 --- /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/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