Skip to content

Commit

Permalink
Added a special case to handle paginating with a negative offset (-X …
Browse files Browse the repository at this point in the history
…to 0).

  * This is needed for getting done iterations.
  • Loading branch information
forest committed Mar 26, 2014
1 parent fa553f5 commit a4401ee
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 1 deletion.
10 changes: 10 additions & 0 deletions lib/tracker_api/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,16 @@ def initialize(headers)
@limit = headers['x-tracker-pagination-limit'].to_i
@offset = headers['x-tracker-pagination-offset'].to_i
@returned = headers['x-tracker-pagination-returned'].to_i

# if offset is negative (e.g. Iterations Endpoint).
# For the 'Done' scope, negative numbers can be passed, which
# specifies the number of iterations preceding the 'Current' iteration.
# then need to adjust the negative offset to account for a smaller total,
# and set total to zero since we are paginating from -X to 0.
if @offset < 0
@offset = -@total if @offset.abs > @total
@total = 0
end
end

def more?
Expand Down
11 changes: 11 additions & 0 deletions test/client_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,16 @@
paged_stories.map(&:id).sort.uniq.must_equal unpaged_stories.map(&:id).sort.uniq
end
end

it 'can handle negative offsets' do
VCR.use_cassette('client: done iterations with pagination', record: :new_episodes) do
project = client.project(project_id)

done_iterations = project.iterations(scope: :done, offset: -12, limit: 5)

done_iterations.wont_be_empty
done_iterations.length.must_be :<=, 12
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"http_interactions":[{"request":{"method":"get","uri":"https://www.pivotaltracker.com/services/v5/projects/1027488","body":{"encoding":"US-ASCII","string":""},"headers":{"User-Agent":["Ruby/2.0.0 (x86_64-darwin13.0.2; ruby) TrackerApi/0.2.0 Faraday/0.8.9"],"X-TrackerToken":["0de3ac29f13082f0c16ed76f3f3f6895"]}},"response":{"status":{"code":200,"message":null},"headers":{"content-type":["application/json; charset=utf-8"],"transfer-encoding":["chunked"],"connection":["close"],"status":["200"],"x-powered-by":["Phusion Passenger (mod_rails/mod_rack) 3.0.14"],"x-tracker-project-version":["1"],"cache-control":["private, max-age=0, must-revalidate"],"x-runtime":["40"],"etag":["\"24d9e32f361b5a8e2b83e7f7f0a1558b\""],"server":["nginx/1.2.2 + Phusion Passenger 3.0.14 (mod_rails/mod_rack)"],"access-control-allow-origin":["*"],"access-control-allow-credentials":["false"],"access-control-allow-methods":["GET, POST, PUT, DELETE, OPTIONS"],"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"]},"body":{"encoding":"UTF-8","string":"{\n \"enable_following\": true,\n \"account_id\": 621384,\n \"version\": 1,\n \"atom_enabled\": false,\n \"enable_planned_mode\": false,\n \"bugs_and_chores_are_estimatable\": false,\n \"has_google_domain\": false,\n \"id\": 1027488,\n \"number_of_done_iterations_to_show\": 12,\n \"velocity_averaged_over\": 3,\n \"kind\": \"project\",\n \"created_at\": \"2014-03-02T07:11:04Z\",\n \"start_time\": \"2014-02-10T08:00:00Z\",\n \"public\": false,\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"profile_content\": \"This is a demo project, created by Tracker, with example stories for a simple shopping web site.\",\n \"enable_tasks\": true,\n \"enable_incoming_emails\": true,\n \"point_scale_is_custom\": false,\n \"initial_velocity\": 10,\n \"time_zone\": {\n \"olson_name\": \"America/Los_Angeles\",\n \"kind\": \"time_zone\",\n \"offset\": \"-07:00\"\n },\n \"week_start_day\": \"Monday\",\n \"iteration_length\": 1,\n \"name\": \"My Sample Project\",\n \"current_iteration_number\": 7,\n \"point_scale\": \"0,1,2,3\"\n}"},"http_version":null},"recorded_at":"Wed, 26 Mar 2014 05:49:42 GMT"},{"request":{"method":"get","uri":"https://www.pivotaltracker.com/services/v5/projects/1027488/iterations?scope=done&offset=-12&limit=5","body":{"encoding":"US-ASCII","string":""},"headers":{"User-Agent":["Ruby/2.0.0 (x86_64-darwin13.0.2; ruby) TrackerApi/0.2.0 Faraday/0.8.9"],"X-TrackerToken":["0de3ac29f13082f0c16ed76f3f3f6895"]}},"response":{"status":{"code":200,"message":null},"headers":{"content-type":["application/json; charset=utf-8"],"transfer-encoding":["chunked"],"connection":["close"],"status":["200"],"x-powered-by":["Phusion Passenger (mod_rails/mod_rack) 3.0.14"],"x-tracker-pagination-returned":["5"],"x-tracker-project-version":["1"],"x-tracker-pagination-limit":["5"],"x-tracker-pagination-total":["6"],"cache-control":["private, max-age=0, must-revalidate"],"x-runtime":["187"],"etag":["\"b96f6d7d4a3d6c0160bca9addeda3beb\""],"x-tracker-pagination-offset":["-12"],"server":["nginx/1.2.2 + Phusion Passenger 3.0.14 (mod_rails/mod_rack)"],"access-control-allow-origin":["*"],"access-control-allow-credentials":["false"],"access-control-allow-methods":["GET, POST, PUT, DELETE, OPTIONS"],"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"]},"body":{"encoding":"UTF-8","string":"[\n {\n \"finish\": \"2014-02-17T08:00:00Z\",\n \"stories\": [\n {\n \"current_state\": \"accepted\",\n \"id\": 66727974,\n \"description\": \"We need 2 machines set up\",\n \"labels\": [\n\n ],\n \"project_id\": 1027488,\n \"story_type\": \"chore\",\n \"kind\": \"story\",\n \"accepted_at\": \"2014-02-11T00:00:00Z\",\n \"created_at\": \"2014-02-10T00:00:00Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"owner_ids\": [\n\n ],\n \"url\": \"http://www.pivotaltracker.com/story/show/66727974\",\n \"name\": \"Setup development environment\",\n \"requested_by_id\": 1266314\n },\n {\n \"current_state\": \"accepted\",\n \"id\": 66727976,\n \"description\": \"Should be accessible from outside the network, with basic auth\",\n \"labels\": [\n {\n \"id\": 7849078,\n \"project_id\": 1027488,\n \"kind\": \"label\",\n \"created_at\": \"2014-03-02T07:11:04Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"name\": \"deployment\"\n }\n ],\n \"project_id\": 1027488,\n \"story_type\": \"chore\",\n \"kind\": \"story\",\n \"accepted_at\": \"2014-02-11T00:00:00Z\",\n \"created_at\": \"2014-02-10T00:00:00Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"owner_ids\": [\n\n ],\n \"url\": \"http://www.pivotaltracker.com/story/show/66727976\",\n \"name\": \"Setup demo server\",\n \"requested_by_id\": 1266314\n },\n {\n \"current_state\": \"accepted\",\n \"id\": 66727978,\n \"description\": \"Admin should be a special user type. We can create the first admin user directly in the DB, but let's encrypt the password.\",\n \"labels\": [\n {\n \"id\": 7849080,\n \"project_id\": 1027488,\n \"kind\": \"label\",\n \"created_at\": \"2014-03-02T07:11:04Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"name\": \"admin\"\n }\n ],\n \"project_id\": 1027488,\n \"story_type\": \"feature\",\n \"estimate\": 2,\n \"kind\": \"story\",\n \"accepted_at\": \"2014-02-11T00:00:00Z\",\n \"created_at\": \"2014-02-10T00:00:00Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"owner_ids\": [\n\n ],\n \"url\": \"http://www.pivotaltracker.com/story/show/66727978\",\n \"name\": \"Admin should be able to login\",\n \"requested_by_id\": 1266314\n },\n {\n \"current_state\": \"accepted\",\n \"id\": 66727980,\n \"description\": \"Product information includes title, description, price, SKU.\",\n \"labels\": [\n {\n \"id\": 7849080,\n \"project_id\": 1027488,\n \"kind\": \"label\",\n \"created_at\": \"2014-03-02T07:11:04Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"name\": \"admin\"\n }\n ],\n \"project_id\": 1027488,\n \"story_type\": \"feature\",\n \"estimate\": 1,\n \"kind\": \"story\",\n \"accepted_at\": \"2014-02-11T00:00:00Z\",\n \"created_at\": \"2014-02-10T00:00:00Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"owner_ids\": [\n\n ],\n \"url\": \"http://www.pivotaltracker.com/story/show/66727980\",\n \"name\": \"Admin should be able to create new product\",\n \"requested_by_id\": 1266314\n },\n {\n \"current_state\": \"accepted\",\n \"id\": 66727982,\n \"labels\": [\n {\n \"id\": 7849080,\n \"project_id\": 1027488,\n \"kind\": \"label\",\n \"created_at\": \"2014-03-02T07:11:04Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"name\": \"admin\"\n }\n ],\n \"project_id\": 1027488,\n \"story_type\": \"feature\",\n \"estimate\": 2,\n \"kind\": \"story\",\n \"accepted_at\": \"2014-02-11T00:00:00Z\",\n \"created_at\": \"2014-02-10T00:00:00Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"owner_ids\": [\n\n ],\n \"url\": \"http://www.pivotaltracker.com/story/show/66727982\",\n \"name\": \"Admin should be able to upload product photo\",\n \"requested_by_id\": 1266314\n }\n ],\n \"project_id\": 1027488,\n \"team_strength\": 1,\n \"kind\": \"iteration\",\n \"number\": 1,\n \"start\": \"2014-02-10T08:00:00Z\"\n },\n {\n \"finish\": \"2014-02-24T08:00:00Z\",\n \"stories\": [\n {\n \"current_state\": \"accepted\",\n \"id\": 66727984,\n \"labels\": [\n {\n \"id\": 7849080,\n \"project_id\": 1027488,\n \"kind\": \"label\",\n \"created_at\": \"2014-03-02T07:11:04Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"name\": \"admin\"\n }\n ],\n \"project_id\": 1027488,\n \"story_type\": \"feature\",\n \"estimate\": 3,\n \"kind\": \"story\",\n \"accepted_at\": \"2014-02-18T00:00:00Z\",\n \"created_at\": \"2014-02-10T00:00:00Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"owner_ids\": [\n\n ],\n \"url\": \"http://www.pivotaltracker.com/story/show/66727984\",\n \"name\": \"Admin should be able to upload multiple product photos and mark one as the primary\",\n \"requested_by_id\": 1266314\n },\n {\n \"current_state\": \"accepted\",\n \"id\": 66727986,\n \"labels\": [\n {\n \"id\": 7849082,\n \"project_id\": 1027488,\n \"kind\": \"label\",\n \"created_at\": \"2014-03-02T07:11:04Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"name\": \"shopping\"\n }\n ],\n \"project_id\": 1027488,\n \"story_type\": \"feature\",\n \"estimate\": 2,\n \"kind\": \"story\",\n \"accepted_at\": \"2014-02-18T00:00:00Z\",\n \"created_at\": \"2014-02-10T00:00:00Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"owner_ids\": [\n\n ],\n \"url\": \"http://www.pivotaltracker.com/story/show/66727986\",\n \"name\": \"Shopper should see list of products, with primary photo as thumbnail\",\n \"requested_by_id\": 1266314\n },\n {\n \"current_state\": \"accepted\",\n \"id\": 66727988,\n \"labels\": [\n {\n \"id\": 7849082,\n \"project_id\": 1027488,\n \"kind\": \"label\",\n \"created_at\": \"2014-03-02T07:11:04Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"name\": \"shopping\"\n }\n ],\n \"project_id\": 1027488,\n \"story_type\": \"feature\",\n \"estimate\": 1,\n \"kind\": \"story\",\n \"accepted_at\": \"2014-02-18T00:00:00Z\",\n \"created_at\": \"2014-02-10T00:00:00Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"owner_ids\": [\n\n ],\n \"url\": \"http://www.pivotaltracker.com/story/show/66727988\",\n \"name\": \"Product browsing should be paginated, with 10 products per page\",\n \"requested_by_id\": 1266314\n },\n {\n \"current_state\": \"accepted\",\n \"id\": 66727990,\n \"labels\": [\n {\n \"id\": 7849082,\n \"project_id\": 1027488,\n \"kind\": \"label\",\n \"created_at\": \"2014-03-02T07:11:04Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"name\": \"shopping\"\n },\n {\n \"id\": 7849084,\n \"project_id\": 1027488,\n \"kind\": \"label\",\n \"created_at\": \"2014-03-02T07:11:05Z\",\n \"updated_at\": \"2014-03-02T07:11:05Z\",\n \"name\": \"usability\"\n }\n ],\n \"project_id\": 1027488,\n \"story_type\": \"feature\",\n \"estimate\": 2,\n \"kind\": \"story\",\n \"accepted_at\": \"2014-02-18T00:00:00Z\",\n \"created_at\": \"2014-02-10T00:00:00Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"owner_ids\": [\n\n ],\n \"url\": \"http://www.pivotaltracker.com/story/show/66727990\",\n \"name\": \"Make product browsing pagination AJAXy\",\n \"requested_by_id\": 1266314\n },\n {\n \"current_state\": \"accepted\",\n \"id\": 66727992,\n \"labels\": [\n {\n \"id\": 7849080,\n \"project_id\": 1027488,\n \"kind\": \"label\",\n \"created_at\": \"2014-03-02T07:11:04Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"name\": \"admin\"\n }\n ],\n \"project_id\": 1027488,\n \"story_type\": \"feature\",\n \"estimate\": 3,\n \"kind\": \"story\",\n \"accepted_at\": \"2014-02-18T00:00:00Z\",\n \"created_at\": \"2014-02-10T00:00:00Z\",\n \"updated_at\": \"2014-03-02T07:11:05Z\",\n \"owner_ids\": [\n\n ],\n \"url\": \"http://www.pivotaltracker.com/story/show/66727992\",\n \"name\": \"Admin should be able to import multiple new products from CSV file\",\n \"requested_by_id\": 1266314\n }\n ],\n \"project_id\": 1027488,\n \"team_strength\": 1,\n \"kind\": \"iteration\",\n \"number\": 2,\n \"start\": \"2014-02-17T08:00:00Z\"\n },\n {\n \"finish\": \"2014-03-03T08:00:00Z\",\n \"stories\": [\n {\n \"current_state\": \"accepted\",\n \"id\": 66727994,\n \"labels\": [\n {\n \"id\": 7849082,\n \"project_id\": 1027488,\n \"kind\": \"label\",\n \"created_at\": \"2014-03-02T07:11:04Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"name\": \"shopping\"\n }\n ],\n \"project_id\": 1027488,\n \"story_type\": \"feature\",\n \"estimate\": 1,\n \"kind\": \"story\",\n \"accepted_at\": \"2014-03-02T00:00:00Z\",\n \"created_at\": \"2014-02-17T00:00:00Z\",\n \"updated_at\": \"2014-03-02T07:11:05Z\",\n \"owner_ids\": [\n\n ],\n \"url\": \"http://www.pivotaltracker.com/story/show/66727994\",\n \"name\": \"Shopper should be able to click on a product, and see all product details, including photos\",\n \"requested_by_id\": 1266314\n },\n {\n \"current_state\": \"accepted\",\n \"id\": 66727996,\n \"labels\": [\n {\n \"id\": 7849086,\n \"project_id\": 1027488,\n \"kind\": \"label\",\n \"created_at\": \"2014-03-02T07:11:05Z\",\n \"updated_at\": \"2014-03-02T07:11:05Z\",\n \"name\": \"cart\"\n },\n {\n \"id\": 7849082,\n \"project_id\": 1027488,\n \"kind\": \"label\",\n \"created_at\": \"2014-03-02T07:11:04Z\",\n \"updated_at\": \"2014-03-02T07:11:04Z\",\n \"name\": \"shopping\"\n }\n ],\n \"project_id\": 1027488,\n \"story_type\": \"feature\",\n \"estimate\": 1,\n \"kind\": \"story\",\n \"accepted_at\": \"2014-03-02T07:11:05Z\",\n \"created_at\": \"2014-02-17T00:00:00Z\",\n \"updated_at\": \"2014-03-02T07:11:05Z\",\n \"owner_ids\": [\n\n ],\n \"url\": \"http://www.pivotaltracker.com/story/show/66727996\",\n \"name\": \"Shopper should be able to add product to shopping cart\",\n \"requested_by_id\": 1266314\n }\n ],\n \"project_id\": 1027488,\n \"team_strength\": 1,\n \"kind\": \"iteration\",\n \"number\": 3,\n \"start\": \"2014-02-24T08:00:00Z\"\n },\n {\n \"finish\": \"2014-03-10T07:00:00Z\",\n \"stories\": [\n\n ],\n \"project_id\": 1027488,\n \"team_strength\": 1,\n \"kind\": \"iteration\",\n \"number\": 4,\n \"start\": \"2014-03-03T08:00:00Z\"\n },\n {\n \"finish\": \"2014-03-17T07:00:00Z\",\n \"stories\": [\n\n ],\n \"project_id\": 1027488,\n \"team_strength\": 1,\n \"kind\": \"iteration\",\n \"number\": 5,\n \"start\": \"2014-03-10T07:00:00Z\"\n }\n]"},"http_version":null},"recorded_at":"Wed, 26 Mar 2014 05:49:43 GMT"},{"request":{"method":"get","uri":"https://www.pivotaltracker.com/services/v5/projects/1027488/iterations?scope=done&offset=-1&limit=5","body":{"encoding":"US-ASCII","string":""},"headers":{"User-Agent":["Ruby/2.0.0 (x86_64-darwin13.0.2; ruby) TrackerApi/0.2.0 Faraday/0.8.9"],"X-TrackerToken":["0de3ac29f13082f0c16ed76f3f3f6895"]}},"response":{"status":{"code":200,"message":null},"headers":{"content-type":["application/json; charset=utf-8"],"transfer-encoding":["chunked"],"connection":["close"],"status":["200"],"x-powered-by":["Phusion Passenger (mod_rails/mod_rack) 3.0.14"],"x-tracker-pagination-returned":["1"],"x-tracker-project-version":["1"],"x-tracker-pagination-limit":["5"],"x-tracker-pagination-total":["6"],"cache-control":["private, max-age=0, must-revalidate"],"x-runtime":["90"],"etag":["\"8e04bde82acfaada287cd50c67a577c8\""],"x-tracker-pagination-offset":["-1"],"server":["nginx/1.2.2 + Phusion Passenger 3.0.14 (mod_rails/mod_rack)"],"access-control-allow-origin":["*"],"access-control-allow-credentials":["false"],"access-control-allow-methods":["GET, POST, PUT, DELETE, OPTIONS"],"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"]},"body":{"encoding":"UTF-8","string":"[\n {\n \"finish\": \"2014-03-24T07:00:00Z\",\n \"stories\": [\n\n ],\n \"project_id\": 1027488,\n \"team_strength\": 1,\n \"kind\": \"iteration\",\n \"number\": 6,\n \"start\": \"2014-03-17T07:00:00Z\"\n }\n]"},"http_version":null},"recorded_at":"Wed, 26 Mar 2014 05:49:43 GMT"}],"recorded_with":"VCR 2.8.0"}
Loading

0 comments on commit a4401ee

Please sign in to comment.