kanbantool 0.0.1
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.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +59 -0
- data/Rakefile +9 -0
- data/kanbantool.gemspec +28 -0
- data/lib/kanbantool.rb +11 -0
- data/lib/kanbantool/board.rb +34 -0
- data/lib/kanbantool/client.rb +72 -0
- data/lib/kanbantool/task.rb +18 -0
- data/lib/kanbantool/version.rb +3 -0
- data/spec/cassettes/board.yml +50 -0
- data/spec/cassettes/boards.yml +59 -0
- data/spec/cassettes/tasks.yml +73 -0
- data/spec/lib/kanbantool/board_spec.rb +74 -0
- data/spec/lib/kanbantool/client_spec.rb +51 -0
- data/spec/lib/kanbantool/task_spec.rb +39 -0
- data/spec/spec_helper.rb +18 -0
- metadata +167 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Tim Blair
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
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:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# Kanban Tool
|
2
|
+
|
3
|
+
A Ruby wrapper library for accessing the [Kanban Tool API][kt-api].
|
4
|
+
|
5
|
+
> Note: this is currently a limited, read-only interface. Contributions
|
6
|
+
> to extend the functionality are welcome.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'kanbantool'
|
14
|
+
```
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
```sh
|
19
|
+
bundle
|
20
|
+
```
|
21
|
+
|
22
|
+
Or install it yourself as:
|
23
|
+
|
24
|
+
```sh
|
25
|
+
gem install kanbantool
|
26
|
+
```
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
Make sure you have an [API key][get-key], then create a client:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
client = KanbanTool::Client.new(SUBDOMAIN, API_KEY}
|
34
|
+
```
|
35
|
+
|
36
|
+
You can then call methods on the client to retrieve data from the API:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
# Retrieve an array of all boards under this account
|
40
|
+
client.boards #=> [#<KanbanTool::Board:0x00 ...>, ...]
|
41
|
+
|
42
|
+
# Retrieve a single board, including stages
|
43
|
+
client.board(BOARD_ID) #=> #<KanbanTool::Board:0x00 ...>
|
44
|
+
|
45
|
+
# Retrieve an array of all tasks for a specific board
|
46
|
+
client.tasks(BOARD_ID) #=> [#<KanbanTool::Task:0x00 ...>, ... ]
|
47
|
+
```
|
48
|
+
|
49
|
+
## Contributing
|
50
|
+
|
51
|
+
1. [Fork it][fork-it]
|
52
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
53
|
+
3. Commit your changes and tests (`git commit -am 'Add some feature'`)
|
54
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
55
|
+
5. Create new Pull Request
|
56
|
+
|
57
|
+
[kt-api]: http://kanbantool.com/about/api
|
58
|
+
[get-key]: http://gppmt.kanbantool.com/profile/api_token
|
59
|
+
[fork-it]: https://github.com/timblair/kanbantool/fork
|
data/Rakefile
ADDED
data/kanbantool.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'kanbantool/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "kanbantool"
|
8
|
+
spec.version = KanbanTool::VERSION
|
9
|
+
spec.authors = ["Tim Blair"]
|
10
|
+
spec.email = ["tim@bla.ir"]
|
11
|
+
spec.description = %q{Easy access to Kanban Tool's API}
|
12
|
+
spec.summary = %q{Easy access to Kanban Tool's API}
|
13
|
+
spec.homepage = "https://github.com/timblair/kanbantool"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "httparty", "~> 0.11.0"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "minitest", "~> 5.0.0"
|
26
|
+
spec.add_development_dependency "webmock", "< 1.10.0"
|
27
|
+
spec.add_development_dependency "vcr", "~> 2.4.0"
|
28
|
+
end
|
data/lib/kanbantool.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module KanbanTool
|
2
|
+
class Board
|
3
|
+
|
4
|
+
class Stage < Struct.new(:id, :name, :description, :position); end
|
5
|
+
|
6
|
+
FIELDS = %w{ id name description created_at version last_activity_on }
|
7
|
+
FIELDS.each { |f| attr_reader f.to_sym }
|
8
|
+
|
9
|
+
attr_reader :stages
|
10
|
+
|
11
|
+
def self.create_from_hash(hash)
|
12
|
+
board = self.new
|
13
|
+
board.load!(hash)
|
14
|
+
board.load_stages!(hash["workflow_stages"]) unless hash["workflow_stages"].nil?
|
15
|
+
board
|
16
|
+
end
|
17
|
+
|
18
|
+
def load!(hash)
|
19
|
+
FIELDS.each { |f| instance_variable_set("@#{f}".to_sym, hash[f]) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def load_stages!(array)
|
23
|
+
@stages = []
|
24
|
+
array.each do |s|
|
25
|
+
@stages << Stage.new( s["id"], s["name"], s["description"], s["position"] ).freeze
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def stage(id)
|
30
|
+
stages.first { |s| s.id == id }
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require "httparty"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
module KanbanTool
|
5
|
+
class Client
|
6
|
+
include HTTParty
|
7
|
+
|
8
|
+
attr_reader :domain, :token
|
9
|
+
|
10
|
+
def initialize(domain, token)
|
11
|
+
@domain = domain
|
12
|
+
@token = token
|
13
|
+
end
|
14
|
+
|
15
|
+
def boards
|
16
|
+
get("boards").collect do |board|
|
17
|
+
Board.create_from_hash board
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def board(board_id)
|
22
|
+
Board.create_from_hash get("boards/#{board_id}")
|
23
|
+
end
|
24
|
+
|
25
|
+
def users(board_id)
|
26
|
+
get("boards/#{board_id}/users")
|
27
|
+
end
|
28
|
+
|
29
|
+
def tasks(board_id)
|
30
|
+
get("boards/#{board_id}/tasks").collect do |task|
|
31
|
+
Task.create_from_hash task
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def activity(board_id)
|
36
|
+
get("boards/#{board_id}/changelog")
|
37
|
+
end
|
38
|
+
|
39
|
+
def api_url
|
40
|
+
"https://#{domain}.#{KanbanTool::API_DOMAIN}#{KanbanTool::API_PATH}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def url_for(path)
|
44
|
+
"#{api_url}#{path}.json"
|
45
|
+
end
|
46
|
+
|
47
|
+
def headers
|
48
|
+
{ "X-KanbanToolToken" => token }
|
49
|
+
end
|
50
|
+
|
51
|
+
def params
|
52
|
+
{ :headers => headers }
|
53
|
+
end
|
54
|
+
|
55
|
+
def get(path)
|
56
|
+
r = HTTParty.get url_for(path), params
|
57
|
+
raise "Error: #{url_for(path)} => #{r.inspect}" if r.code != 200
|
58
|
+
unwrap JSON.parse(r.body)
|
59
|
+
end
|
60
|
+
|
61
|
+
def unwrap(data)
|
62
|
+
if data.is_a? Array
|
63
|
+
data.collect { |item| unwrap item }
|
64
|
+
else
|
65
|
+
keys = %w{ board task shared_item_user }
|
66
|
+
key = keys.find { |key| !data[key].nil? }
|
67
|
+
data.include?(key) ? data[key] : data
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module KanbanTool
|
2
|
+
class Task
|
3
|
+
|
4
|
+
FIELDS = %w{ id name description created_at updated_at archived_at assigned_user }
|
5
|
+
FIELDS.each { |f| attr_reader f.to_sym }
|
6
|
+
|
7
|
+
def self.create_from_hash(hash)
|
8
|
+
task = self.new
|
9
|
+
task.load!(hash)
|
10
|
+
task
|
11
|
+
end
|
12
|
+
|
13
|
+
def load!(hash)
|
14
|
+
FIELDS.each { |f| instance_variable_set("@#{f}".to_sym, hash[f]) }
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://test.kanbantool.com/api/v1/boards/12345.json
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
X-Kanbantooltoken:
|
11
|
+
- 123456789ABC
|
12
|
+
response:
|
13
|
+
status:
|
14
|
+
code: 200
|
15
|
+
message: OK
|
16
|
+
headers:
|
17
|
+
Date:
|
18
|
+
- Fri, 10 May 2013 14:35:50 GMT
|
19
|
+
Content-Type:
|
20
|
+
- application/json; charset=utf-8
|
21
|
+
Transfer-Encoding:
|
22
|
+
- chunked
|
23
|
+
Connection:
|
24
|
+
- keep-alive
|
25
|
+
Status:
|
26
|
+
- '200'
|
27
|
+
X-Rack-Cache:
|
28
|
+
- miss
|
29
|
+
Cache-Control:
|
30
|
+
- max-age=0, private, must-revalidate
|
31
|
+
Etag:
|
32
|
+
- ! '"56215f2e9fdc84ee89170720de5cdfe9"'
|
33
|
+
X-Runtime:
|
34
|
+
- '0.095858'
|
35
|
+
X-Ua-Compatible:
|
36
|
+
- IE=Edge,chrome=1
|
37
|
+
Server:
|
38
|
+
- kanbantool.com
|
39
|
+
body:
|
40
|
+
encoding: US-ASCII
|
41
|
+
string: ! '{"board":{"swimlanes":[{"board_id":12345,"name":"Project status","id":77669,"limit":null,"position":1,"description":""}],"owner_id":22825,"created_at":"2013-05-02T15:01:16+01:00","cumulative_flow_updated_at":"2013-05-10T03:34:05+01:00","folder_id":null,"version":178,"board_template_id":"personal_basic","last_activity_on":"2013-05-10","deleted_at":null,"id":12345,"name":"Project
|
42
|
+
Status Board","workflow_stages":[{"board_id":12345,"lane_width":1,"lane_type_id":null,"name":null,"id":284733,"parent_id":null,"limit":null,"position":1,"description":null},{"board_id":12345,"lane_width":1,"lane_type_id":null,"name":"Backlog","id":284735,"parent_id":284733,"limit":null,"position":1,"description":""},{"board_id":12345,"lane_width":1,"lane_type_id":null,"name":"Briefing","id":286335,"parent_id":284733,"limit":null,"position":1,"description":"Actions
|
43
|
+
to be carried out outside of the project team prior to scheduling, requirements
|
44
|
+
gathering and development."},{"board_id":12345,"lane_width":1,"lane_type_id":null,"name":"Waiting
|
45
|
+
for resource","id":286337,"parent_id":284733,"limit":null,"position":1,"description":""},{"board_id":12345,"lane_width":1,"lane_type_id":null,"name":"Functional
|
46
|
+
spec","id":284737,"parent_id":284733,"limit":null,"position":1,"description":""},{"board_id":12345,"lane_width":1,"lane_type_id":null,"name":"Technical
|
47
|
+
spec","id":284755,"parent_id":284733,"limit":null,"position":1,"description":""},{"board_id":12345,"lane_width":1,"lane_type_id":null,"name":"Development","id":284739,"parent_id":284733,"limit":null,"position":1,"description":""},{"board_id":12345,"lane_width":1,"lane_type_id":null,"name":"QA","id":284741,"parent_id":284733,"limit":null,"position":1,"description":""},{"board_id":12345,"lane_width":1,"lane_type_id":null,"name":"Live","id":284743,"parent_id":284733,"limit":null,"position":1,"description":""}],"external_id_sequence":1,"description":"","position":null,"card_types":[{"board_id":12345,"is_default":true,"color_ref":"yellow","name":"yellow","id":250943,"is_disabled":false,"position":1},{"board_id":12345,"is_default":false,"color_ref":"orange","name":"orange","id":250945,"is_disabled":false,"position":2},{"board_id":12345,"is_default":false,"color_ref":"red","name":"red","id":250947,"is_disabled":false,"position":3},{"board_id":12345,"is_default":false,"color_ref":"blue","name":"blue","id":250949,"is_disabled":false,"position":4},{"board_id":12345,"is_default":false,"color_ref":"green","name":"green","id":250951,"is_disabled":false,"position":5},{"board_id":12345,"is_default":false,"color_ref":"white","name":"white","id":250953,"is_disabled":false,"position":6}]}}'
|
48
|
+
http_version:
|
49
|
+
recorded_at: Fri, 10 May 2013 14:35:50 GMT
|
50
|
+
recorded_with: VCR 2.4.0
|
@@ -0,0 +1,59 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://test.kanbantool.com/api/v1/boards.json
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
X-Kanbantooltoken:
|
11
|
+
- 123456789ABC
|
12
|
+
response:
|
13
|
+
status:
|
14
|
+
code: 200
|
15
|
+
message: OK
|
16
|
+
headers:
|
17
|
+
Date:
|
18
|
+
- Fri, 10 May 2013 14:35:49 GMT
|
19
|
+
Content-Type:
|
20
|
+
- application/json; charset=utf-8
|
21
|
+
Transfer-Encoding:
|
22
|
+
- chunked
|
23
|
+
Connection:
|
24
|
+
- keep-alive
|
25
|
+
Status:
|
26
|
+
- '200'
|
27
|
+
X-Rack-Cache:
|
28
|
+
- miss
|
29
|
+
Cache-Control:
|
30
|
+
- max-age=0, private, must-revalidate
|
31
|
+
Etag:
|
32
|
+
- ! '"c3798def8ad2a5c47c71666aab890d61"'
|
33
|
+
X-Runtime:
|
34
|
+
- '2.177222'
|
35
|
+
X-Ua-Compatible:
|
36
|
+
- IE=Edge,chrome=1
|
37
|
+
Server:
|
38
|
+
- kanbantool.com
|
39
|
+
body:
|
40
|
+
encoding: US-ASCII
|
41
|
+
string: ! '[{ "board":{ "owner_id":
|
42
|
+
null,"created_at":"2013-04-05T14:49:07+01:00","cumulative_flow_updated_at":"2013-05-10T03:30:45+01:00","folder_id":
|
43
|
+
3029,"version":
|
44
|
+
620,"board_template_id":"team_basic","last_activity_on":"2013-05-10","deleted_at":
|
45
|
+
null,"id": 33223,"name":"Test Board
|
46
|
+
1","external_id_sequence": 1,"description":"My
|
47
|
+
description","position": null }},{ "board":{ "owner_id":
|
48
|
+
null,"created_at":"2013-04-05T14:49:07+01:00","cumulative_flow_updated_at":"2013-05-10T03:30:45+01:00","folder_id":
|
49
|
+
3029,"version":
|
50
|
+
620,"board_template_id":"team_basic","last_activity_on":"2013-05-10","deleted_at":
|
51
|
+
null,"id": 33223,"name":"Test Board
|
52
|
+
1","external_id_sequence": 1,"folder":{ "owner_id":
|
53
|
+
null,"created_at":"2013-02-07T14:45:54+00:00","deleted_at":
|
54
|
+
null,"name":"Some Folder","id": 3029,"position":
|
55
|
+
null,"description":""},"description":"My
|
56
|
+
description","position": null }}]'
|
57
|
+
http_version:
|
58
|
+
recorded_at: Fri, 10 May 2013 14:35:49 GMT
|
59
|
+
recorded_with: VCR 2.4.0
|
@@ -0,0 +1,73 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://test.kanbantool.com/api/v1/boards/12345/tasks.json
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
X-Kanbantooltoken:
|
11
|
+
- 123456789ABC
|
12
|
+
response:
|
13
|
+
status:
|
14
|
+
code: 200
|
15
|
+
message: OK
|
16
|
+
headers:
|
17
|
+
Date:
|
18
|
+
- Fri, 10 May 2013 14:35:52 GMT
|
19
|
+
Content-Type:
|
20
|
+
- application/json; charset=utf-8
|
21
|
+
Transfer-Encoding:
|
22
|
+
- chunked
|
23
|
+
Connection:
|
24
|
+
- keep-alive
|
25
|
+
Status:
|
26
|
+
- '200'
|
27
|
+
X-Rack-Cache:
|
28
|
+
- miss
|
29
|
+
Cache-Control:
|
30
|
+
- max-age=0, private, must-revalidate
|
31
|
+
Etag:
|
32
|
+
- ! '"c570831d8fdab2d078d64bbdb7162e1e"'
|
33
|
+
X-Runtime:
|
34
|
+
- '0.175887'
|
35
|
+
X-Ua-Compatible:
|
36
|
+
- IE=Edge,chrome=1
|
37
|
+
Server:
|
38
|
+
- kanbantool.com
|
39
|
+
body:
|
40
|
+
encoding: US-ASCII
|
41
|
+
string: ! '[{"task": {"archived_at": null,"assigned_user": {"initials": "TU","name": "Test
|
42
|
+
User"},"assigned_user_id": 2334,"block_reason": null,"card_type_id":
|
43
|
+
250953,"comments_count": 0,"created_at":
|
44
|
+
"2013-05-02T15:12:32+01:00","custom_field_1": null,"custom_field_2":
|
45
|
+
null,"custom_field_3": null,"custom_field_4": null,"custom_field_5":
|
46
|
+
null,"description": "","due_date": null,"external_id": null,"external_link":
|
47
|
+
null,"id": 1568915,"name": "Card 1","position": 4,"priority": 0,"size_estimate":
|
48
|
+
"1.0","subtask_search_tags": null,"subtasks_completed_count":
|
49
|
+
0,"subtasks_count": 0,"swimlane_id": 77669,"tags": "","updated_at":
|
50
|
+
"2013-05-02T16:19:34+01:00","workflow_stage_id": 284735}},{"task":
|
51
|
+
{"archived_at": null,"assigned_user": {"initials": "AU","name": "Another
|
52
|
+
User"},"assigned_user_id": 2344,"block_reason": null,"card_type_id":
|
53
|
+
250953,"comments_count": 0,"created_at":
|
54
|
+
"2013-05-02T15:12:46+01:00","custom_field_1": null,"custom_field_2":
|
55
|
+
null,"custom_field_3": null,"custom_field_4": null,"custom_field_5":
|
56
|
+
null,"description": "","due_date": null,"external_id": null,"external_link":
|
57
|
+
null,"id": 1568917,"name": "Card 2","position": 3,"priority": 0,"size_estimate":
|
58
|
+
"1.0","subtask_search_tags": null,"subtasks_completed_count":
|
59
|
+
0,"subtasks_count": 0,"swimlane_id": 77669,"tags": "","updated_at":
|
60
|
+
"2013-05-02T16:19:33+01:00","workflow_stage_id": 284735}},{"task":
|
61
|
+
{"archived_at": null,"assigned_user_id": null,"block_reason":
|
62
|
+
null,"card_type_id": 250953,"comments_count": 0,"created_at":
|
63
|
+
"2013-05-02T15:13:23+01:00","custom_field_1": null,"custom_field_2":
|
64
|
+
null,"custom_field_3": null,"custom_field_4": null,"custom_field_5":
|
65
|
+
null,"description": "","due_date": null,"external_id": null,"external_link":
|
66
|
+
null,"id": 1568919,"name": "Interests Searching/Niching","position":
|
67
|
+
1,"priority": 0,"size_estimate": "1.0","subtask_search_tags":
|
68
|
+
null,"subtasks_completed_count": 0,"subtasks_count": 0,"swimlane_id":
|
69
|
+
77669,"tags": "","updated_at": "2013-05-02T15:13:23+01:00","workflow_stage_id":
|
70
|
+
284735}}]'
|
71
|
+
http_version:
|
72
|
+
recorded_at: Fri, 10 May 2013 14:35:52 GMT
|
73
|
+
recorded_with: VCR 2.4.0
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require (File.expand_path('./../../../spec_helper', __FILE__))
|
2
|
+
|
3
|
+
describe KanbanTool::Board do
|
4
|
+
|
5
|
+
let(:board) { KanbanTool::Board.new }
|
6
|
+
let(:board_params) { KanbanTool::Board::FIELDS.inject({}) { |h,f| h[f] = f*3; h } }
|
7
|
+
let(:board_hash) { board_params }
|
8
|
+
let(:stage) { {"id" => "1", "name" => "foo", "description" => "bar", "position" => 1} }
|
9
|
+
let(:stages) { [stage, stage, stage] }
|
10
|
+
|
11
|
+
describe "#load!" do
|
12
|
+
let(:extra_hash_param) { board_hash.merge({ "foo" => "bar" }) }
|
13
|
+
|
14
|
+
it "loads the hash" do
|
15
|
+
board.load!(board_hash)
|
16
|
+
board_hash.each { |k,v| board.send("#{k}".to_sym).must_equal v }
|
17
|
+
end
|
18
|
+
|
19
|
+
it "doesn't import unlisted fields" do
|
20
|
+
board.load!(extra_hash_param)
|
21
|
+
board.instance_variable_get(:@foo).must_be_nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it "overwrites existing values" do
|
25
|
+
board.instance_variable_set(:@id, "x")
|
26
|
+
board.load!(board_hash)
|
27
|
+
board.id.must_equal board_hash["id"]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#load_stages!" do
|
32
|
+
before do
|
33
|
+
board.load_stages!(stages)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "loads all stages" do
|
37
|
+
board.stages.size.must_equal stages.size
|
38
|
+
end
|
39
|
+
|
40
|
+
it "creates Stage objects" do
|
41
|
+
board.stages.each { |s| s.must_be_instance_of KanbanTool::Board::Stage }
|
42
|
+
end
|
43
|
+
|
44
|
+
it "freezes all stages" do
|
45
|
+
board.stages.first.must_be :frozen?
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe ".create_from_hash" do
|
50
|
+
let(:board) { KanbanTool::Board.create_from_hash(board_hash) }
|
51
|
+
|
52
|
+
context "without stages" do
|
53
|
+
it "returns a board instance" do
|
54
|
+
board.must_be_instance_of KanbanTool::Board
|
55
|
+
end
|
56
|
+
|
57
|
+
it "correctly loads the board data" do
|
58
|
+
board_hash.each { |k,v| board.send("#{k}".to_sym).must_equal v }
|
59
|
+
end
|
60
|
+
|
61
|
+
it "handles empty stages" do
|
62
|
+
board.stages.must_be_nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "with stages" do
|
67
|
+
let(:board_hash) { board_params.merge({"workflow_stages" => stages}) }
|
68
|
+
|
69
|
+
it "populates stages" do
|
70
|
+
board.stages.size.must_equal stages.size
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require (File.expand_path('./../../../spec_helper', __FILE__))
|
2
|
+
|
3
|
+
describe KanbanTool::Client do
|
4
|
+
|
5
|
+
let(:client) { KanbanTool::Client.new("test", "123456789ABC") }
|
6
|
+
|
7
|
+
after do
|
8
|
+
VCR.eject_cassette
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#boards" do
|
12
|
+
before do
|
13
|
+
VCR.insert_cassette "boards"
|
14
|
+
end
|
15
|
+
|
16
|
+
subject { client.boards }
|
17
|
+
|
18
|
+
it "returns an array" do
|
19
|
+
subject.must_be_instance_of(Array)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns an array of boards" do
|
23
|
+
subject.each { |b| b.must_be_instance_of(KanbanTool::Board) }
|
24
|
+
end
|
25
|
+
|
26
|
+
it "populates all board objects" do
|
27
|
+
subject.each { |b| b.id.wont_be_nil }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#tasks" do
|
32
|
+
before do
|
33
|
+
VCR.insert_cassette "tasks"
|
34
|
+
end
|
35
|
+
|
36
|
+
subject { client.tasks(12345) }
|
37
|
+
|
38
|
+
it "returns an array" do
|
39
|
+
subject.must_be_instance_of(Array)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "returns an array of tasks" do
|
43
|
+
subject.each { |b| b.must_be_instance_of(KanbanTool::Task) }
|
44
|
+
end
|
45
|
+
|
46
|
+
it "populates all task objects" do
|
47
|
+
subject.each { |b| b.id.wont_be_nil }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require (File.expand_path('./../../../spec_helper', __FILE__))
|
2
|
+
|
3
|
+
describe KanbanTool::Task do
|
4
|
+
|
5
|
+
let(:task) { KanbanTool::Task.new }
|
6
|
+
let(:task_hash) { KanbanTool::Task::FIELDS.inject({}) { |h,f| h[f] = f*3; h } }
|
7
|
+
|
8
|
+
describe "#load!" do
|
9
|
+
let(:extra_hash_param) { task_hash.merge({ "foo" => "bar" }) }
|
10
|
+
|
11
|
+
it "loads the hash" do
|
12
|
+
task.load!(task_hash)
|
13
|
+
task_hash.each { |k,v| task.send("#{k}".to_sym).must_equal v }
|
14
|
+
end
|
15
|
+
|
16
|
+
it "doesn't import unlisted fields" do
|
17
|
+
task.load!(extra_hash_param)
|
18
|
+
task.instance_variable_get(:@foo).must_be_nil
|
19
|
+
end
|
20
|
+
|
21
|
+
it "overwrites existing values" do
|
22
|
+
task.instance_variable_set(:@id, "x")
|
23
|
+
task.load!(task_hash)
|
24
|
+
task.id.must_equal task_hash["id"]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe ".create_from_hash" do
|
29
|
+
let(:task) { KanbanTool::Task.create_from_hash(task_hash) }
|
30
|
+
|
31
|
+
it "returns a task instance" do
|
32
|
+
task.must_be_instance_of KanbanTool::Task
|
33
|
+
end
|
34
|
+
|
35
|
+
it "correctly loads the task data" do
|
36
|
+
task_hash.each { |k,v| task.send("#{k}".to_sym).must_equal v }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require(File.expand_path("../../lib/kanbantool", __FILE__))
|
2
|
+
|
3
|
+
require "minitest/autorun"
|
4
|
+
require "webmock/minitest"
|
5
|
+
require "vcr"
|
6
|
+
|
7
|
+
VCR.configure do |c|
|
8
|
+
c.cassette_library_dir = "spec/cassettes"
|
9
|
+
c.hook_into :webmock
|
10
|
+
end
|
11
|
+
|
12
|
+
module MiniTest
|
13
|
+
class Spec
|
14
|
+
class << self
|
15
|
+
alias_method :context, :describe
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kanbantool
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Tim Blair
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-05-13 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: httparty
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.11.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.11.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bundler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '1.3'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '1.3'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: minitest
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 5.0.0
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 5.0.0
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: webmock
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - <
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 1.10.0
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - <
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 1.10.0
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: vcr
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 2.4.0
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 2.4.0
|
110
|
+
description: Easy access to Kanban Tool's API
|
111
|
+
email:
|
112
|
+
- tim@bla.ir
|
113
|
+
executables: []
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files: []
|
116
|
+
files:
|
117
|
+
- .gitignore
|
118
|
+
- Gemfile
|
119
|
+
- LICENSE.txt
|
120
|
+
- README.md
|
121
|
+
- Rakefile
|
122
|
+
- kanbantool.gemspec
|
123
|
+
- lib/kanbantool.rb
|
124
|
+
- lib/kanbantool/board.rb
|
125
|
+
- lib/kanbantool/client.rb
|
126
|
+
- lib/kanbantool/task.rb
|
127
|
+
- lib/kanbantool/version.rb
|
128
|
+
- spec/cassettes/board.yml
|
129
|
+
- spec/cassettes/boards.yml
|
130
|
+
- spec/cassettes/tasks.yml
|
131
|
+
- spec/lib/kanbantool/board_spec.rb
|
132
|
+
- spec/lib/kanbantool/client_spec.rb
|
133
|
+
- spec/lib/kanbantool/task_spec.rb
|
134
|
+
- spec/spec_helper.rb
|
135
|
+
homepage: https://github.com/timblair/kanbantool
|
136
|
+
licenses:
|
137
|
+
- MIT
|
138
|
+
post_install_message:
|
139
|
+
rdoc_options: []
|
140
|
+
require_paths:
|
141
|
+
- lib
|
142
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
143
|
+
none: false
|
144
|
+
requirements:
|
145
|
+
- - ! '>='
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
|
+
none: false
|
150
|
+
requirements:
|
151
|
+
- - ! '>='
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
requirements: []
|
155
|
+
rubyforge_project:
|
156
|
+
rubygems_version: 1.8.23
|
157
|
+
signing_key:
|
158
|
+
specification_version: 3
|
159
|
+
summary: Easy access to Kanban Tool's API
|
160
|
+
test_files:
|
161
|
+
- spec/cassettes/board.yml
|
162
|
+
- spec/cassettes/boards.yml
|
163
|
+
- spec/cassettes/tasks.yml
|
164
|
+
- spec/lib/kanbantool/board_spec.rb
|
165
|
+
- spec/lib/kanbantool/client_spec.rb
|
166
|
+
- spec/lib/kanbantool/task_spec.rb
|
167
|
+
- spec/spec_helper.rb
|