kanbantool 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in kanbantool.gemspec
4
+ gemspec
@@ -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.
@@ -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
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.test_files = FileList["spec/lib/kanbantool/*_spec.rb"]
6
+ t.verbose = true
7
+ end
8
+
9
+ task :default => :test
@@ -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
@@ -0,0 +1,11 @@
1
+ require "kanbantool/version"
2
+ require "kanbantool/client"
3
+ require "kanbantool/board"
4
+ require "kanbantool/task"
5
+
6
+ module KanbanTool
7
+
8
+ API_DOMAIN = "kanbantool.com"
9
+ API_PATH = "/api/v1/"
10
+
11
+ end
@@ -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,3 @@
1
+ module KanbanTool
2
+ VERSION = "0.0.1"
3
+ 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
@@ -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