ruby-trello-wgibbs 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +37 -0
- data/lib/trello/action.rb +46 -0
- data/lib/trello/association.rb +11 -0
- data/lib/trello/association_proxy.rb +42 -0
- data/lib/trello/authorization.rb +114 -0
- data/lib/trello/basic_data.rb +84 -0
- data/lib/trello/board.rb +95 -0
- data/lib/trello/card.rb +162 -0
- data/lib/trello/checklist.rb +82 -0
- data/lib/trello/client.rb +49 -0
- data/lib/trello/has_actions.rb +9 -0
- data/lib/trello/item.rb +18 -0
- data/lib/trello/item_state.rb +23 -0
- data/lib/trello/label.rb +19 -0
- data/lib/trello/list.rb +71 -0
- data/lib/trello/member.rb +93 -0
- data/lib/trello/multi_association.rb +10 -0
- data/lib/trello/net.rb +37 -0
- data/lib/trello/notification.rb +48 -0
- data/lib/trello/organization.rb +47 -0
- data/lib/trello/string.rb +36 -0
- data/lib/trello/token.rb +24 -0
- data/lib/trello.rb +83 -0
- data/spec/action_spec.rb +71 -0
- data/spec/basic_auth_policy_spec.rb +56 -0
- data/spec/board_spec.rb +196 -0
- data/spec/card_spec.rb +213 -0
- data/spec/checklist_spec.rb +50 -0
- data/spec/client_spec.rb +131 -0
- data/spec/integration/how_to_authorize_spec.rb +53 -0
- data/spec/integration/how_to_use_boards_spec.rb +48 -0
- data/spec/integration/integration_test.rb +40 -0
- data/spec/item_spec.rb +27 -0
- data/spec/item_state_spec.rb +0 -0
- data/spec/list_spec.rb +50 -0
- data/spec/member_spec.rb +92 -0
- data/spec/notification_spec.rb +83 -0
- data/spec/oauth_policy_spec.rb +93 -0
- data/spec/organization_spec.rb +26 -0
- data/spec/spec_helper.rb +244 -0
- data/spec/string_spec.rb +50 -0
- data/spec/token_spec.rb +33 -0
- metadata +220 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'integration/integration_test'
|
3
|
+
|
4
|
+
describe "how to use boards", :broken => true do
|
5
|
+
include IntegrationTest
|
6
|
+
|
7
|
+
context "given a valid access token" do
|
8
|
+
before :all do
|
9
|
+
OAuthPolicy.consumer_credential = OAuthCredential.new @developer_public_key, @developer_secret
|
10
|
+
OAuthPolicy.token = OAuthCredential.new @access_token_key, @access_token_secret
|
11
|
+
Container.set Trello::Authorization, "AuthPolicy", OAuthPolicy
|
12
|
+
end
|
13
|
+
|
14
|
+
after do
|
15
|
+
if @new_board and false == @new_board.closed?
|
16
|
+
@new_board.update_fields 'closed' => true
|
17
|
+
@new_board.save
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "can add a board" do
|
22
|
+
@new_board = Board.create(:name => "An example")
|
23
|
+
@new_board.should_not be_nil
|
24
|
+
@new_board.id.should_not be_nil
|
25
|
+
@new_board.name.should == "An example"
|
26
|
+
@new_board.should_not be_closed
|
27
|
+
end
|
28
|
+
|
29
|
+
it "can read the welcome board" do
|
30
|
+
welcome_board = Board.find @welcome_board
|
31
|
+
welcome_board.name.should === "Welcome Board"
|
32
|
+
welcome_board.id.should === @welcome_board
|
33
|
+
end
|
34
|
+
|
35
|
+
it "can close a board" do
|
36
|
+
@new_board = Board.create(:name => "[#{Time.now}, CLOSED] An example")
|
37
|
+
|
38
|
+
@new_board.update_fields 'closed' => true
|
39
|
+
@new_board.save
|
40
|
+
|
41
|
+
Board.find(@new_board.id).should be_closed
|
42
|
+
end
|
43
|
+
|
44
|
+
it "can list all boards" do
|
45
|
+
Client.get("/members/me/boards/").json_into(Board).should be_an Array
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module IntegrationTest
|
2
|
+
include Trello
|
3
|
+
include Trello::Authorization
|
4
|
+
|
5
|
+
class Container
|
6
|
+
class << self
|
7
|
+
def set(parent, name, value)
|
8
|
+
parent.send :remove_const, name
|
9
|
+
parent.const_set name, value
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.included(klass)
|
15
|
+
klass.class_eval do
|
16
|
+
before :all do
|
17
|
+
# Getting developer/member key
|
18
|
+
# 1. https://trello.com/1/appKey/generate
|
19
|
+
# 2. https://trello.com/1/connect?key=<public_key_here>&name=RubyTrelloIntegrationTests&response_type=token
|
20
|
+
# See: https://trello.com/board/trello-public-api/4ed7e27fe6abb2517a21383d
|
21
|
+
|
22
|
+
@developer_public_key = ENV["DEVELOPER_PUBLIC_KEY"]
|
23
|
+
@developer_secret = ENV["DEVELOPER_SECRET"]
|
24
|
+
@member_token = ENV["MEMBER_TOKEN"]
|
25
|
+
@welcome_board = ENV["WELCOME_BOARD"]
|
26
|
+
@access_token_key = ENV["ACCESS_TOKEN_KEY"]
|
27
|
+
@access_token_secret = ENV["ACCESS_TOKEN_SECRET"]
|
28
|
+
|
29
|
+
WebMock.disable!
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def get(uri)
|
37
|
+
require "rest_client"
|
38
|
+
RestClient.get uri.to_s
|
39
|
+
end
|
40
|
+
end
|
data/spec/item_spec.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Trello
|
4
|
+
describe Item do
|
5
|
+
before(:all) do
|
6
|
+
@detail = {
|
7
|
+
'id' => "abcdef123456789123456789",
|
8
|
+
'name' => "test item",
|
9
|
+
'type' => "check"
|
10
|
+
}
|
11
|
+
|
12
|
+
@item = Item.new(@detail)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "gets its id" do
|
16
|
+
@item.id.should == @detail['id']
|
17
|
+
end
|
18
|
+
|
19
|
+
it "gets its name" do
|
20
|
+
@item.name.should == @detail['name']
|
21
|
+
end
|
22
|
+
|
23
|
+
it "knows its type" do
|
24
|
+
@item.type.should == @detail['type']
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
File without changes
|
data/spec/list_spec.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Trello
|
4
|
+
describe List do
|
5
|
+
include Helpers
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
Client.stub(:get).with("/lists/abcdef123456789123456789").and_return JSON.generate(lists_details.first)
|
9
|
+
Client.stub(:get).with("/boards/abcdef123456789123456789").and_return JSON.generate(boards_details.first)
|
10
|
+
|
11
|
+
@list = List.find("abcdef123456789123456789")
|
12
|
+
end
|
13
|
+
|
14
|
+
context "fields" do
|
15
|
+
it "gets its id" do
|
16
|
+
@list.id.should == lists_details.first['id']
|
17
|
+
end
|
18
|
+
|
19
|
+
it "gets its name" do
|
20
|
+
@list.name.should == lists_details.first['name']
|
21
|
+
end
|
22
|
+
|
23
|
+
it "knows if it is open or closed" do
|
24
|
+
@list.closed.should == lists_details.first['closed']
|
25
|
+
end
|
26
|
+
|
27
|
+
it "has a board" do
|
28
|
+
@list.board.should == Board.new(boards_details.first)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "actions" do
|
33
|
+
it "has a list of actions" do
|
34
|
+
Client.stub(:get).with("/lists/abcdef123456789123456789/actions", { :filter => :all }).and_return actions_payload
|
35
|
+
@list.actions.count.should be > 0
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "cards" do
|
40
|
+
it "has a list of cards" do
|
41
|
+
Client.stub(:get).with("/lists/abcdef123456789123456789/cards", { :filter => :open }).and_return cards_payload
|
42
|
+
@list.cards.count.should be > 0
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it "is not closed" do
|
47
|
+
@list.closed?.should_not be_true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/spec/member_spec.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
# Specs covering the members namespace in the Trello API
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module Trello
|
6
|
+
describe Member do
|
7
|
+
include Helpers
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
Client.stub(:get).with("/members/abcdef123456789012345678").and_return user_payload
|
11
|
+
|
12
|
+
@member = Member.find('abcdef123456789012345678')
|
13
|
+
end
|
14
|
+
|
15
|
+
context "actions" do
|
16
|
+
it "retrieves a list of actions", :refactor => true do
|
17
|
+
Client.stub(:get).with("/members/abcdef123456789012345678/actions", { :filter => :all }).and_return actions_payload
|
18
|
+
@member.actions.count.should be > 0
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "boards" do
|
23
|
+
it "has a list of boards" do
|
24
|
+
Client.stub(:get).with("/members/abcdef123456789012345678/boards", { :filter => :all }).and_return boards_payload
|
25
|
+
boards = @member.boards
|
26
|
+
boards.count.should be > 0
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "cards" do
|
31
|
+
it "has a list of cards" do
|
32
|
+
Client.stub(:get).with("/members/abcdef123456789012345678/cards", { :filter => :open }).and_return cards_payload
|
33
|
+
cards = @member.cards
|
34
|
+
cards.count.should be > 0
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "organizations" do
|
39
|
+
it "has a list of organizations" do
|
40
|
+
Client.stub(:get).with("/members/abcdef123456789012345678/organizations", { :filter => :all }).and_return orgs_payload
|
41
|
+
orgs = @member.organizations
|
42
|
+
orgs.count.should be > 0
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "notifications" do
|
47
|
+
it "has a list of notifications" do
|
48
|
+
Client.stub(:get).with("/members/abcdef123456789012345678/notifications", {}).and_return "[" << notification_payload << "]"
|
49
|
+
@member.notifications.count.should be 1
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "personal" do
|
54
|
+
it "gets the members bio" do
|
55
|
+
@member.bio.should == user_details['bio']
|
56
|
+
end
|
57
|
+
|
58
|
+
it "gets the full name" do
|
59
|
+
@member.full_name.should == user_details['fullName']
|
60
|
+
end
|
61
|
+
|
62
|
+
it "gets the avatar id" do
|
63
|
+
@member.avatar_id.should == user_details['avatarHash']
|
64
|
+
end
|
65
|
+
|
66
|
+
it "returns a valid url for the avatar" do
|
67
|
+
@member.avatar_url(:size => :large).should == "https://trello-avatars.s3.amazonaws.com/abcdef1234567890abcdef1234567890/170.png"
|
68
|
+
@member.avatar_url(:size => :small).should == "https://trello-avatars.s3.amazonaws.com/abcdef1234567890abcdef1234567890/30.png"
|
69
|
+
end
|
70
|
+
|
71
|
+
it "gets the url" do
|
72
|
+
@member.url.should == user_details['url']
|
73
|
+
end
|
74
|
+
|
75
|
+
it "gets the username" do
|
76
|
+
@member.username.should == user_details['username']
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context "modification" do
|
81
|
+
it "lets us know a field has changed without committing it" do
|
82
|
+
@member.changed?.should be_false
|
83
|
+
@member.bio = "New and amazing"
|
84
|
+
@member.changed?.should be_true
|
85
|
+
end
|
86
|
+
|
87
|
+
it "doesn't understand the #id= method" do
|
88
|
+
lambda { @member.id = "42" }.should raise_error NoMethodError
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Trello
|
4
|
+
describe Notification do
|
5
|
+
include Helpers
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
Client.stub(:get).with("/members/abcdef123456789012345678").and_return user_payload
|
9
|
+
member = Member.find("abcdef123456789012345678")
|
10
|
+
Client.stub(:get).with("/members/abcdef123456789012345678/notifications", {}).and_return "[" << notification_payload << "]"
|
11
|
+
@notification = member.notifications.first
|
12
|
+
end
|
13
|
+
|
14
|
+
context "finding" do
|
15
|
+
it "can find a specific notification" do
|
16
|
+
Client.stub(:get).with("/notifications/#{notification_details['id']}").and_return notification_payload
|
17
|
+
Notification.find(notification_details['id']).should == @notification
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "boards" do
|
22
|
+
it "can retrieve the board" do
|
23
|
+
Client.stub(:get).with("/notifications/#{notification_details['id']}/board").and_return JSON.generate(boards_details.first)
|
24
|
+
@notification.board.id.should == boards_details.first['id']
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "lists" do
|
29
|
+
it "can retrieve the list" do
|
30
|
+
Client.stub(:get).with("/notifications/#{notification_details['id']}/list").and_return JSON.generate(lists_details.first)
|
31
|
+
@notification.list.id.should == lists_details.first['id']
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "cards" do
|
36
|
+
it "can retrieve the card" do
|
37
|
+
Client.stub(:get).with("/notifications/#{notification_details['id']}/card").and_return JSON.generate(cards_details.first)
|
38
|
+
@notification.card.id.should == cards_details.first['id']
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "members" do
|
43
|
+
it "can retrieve the member" do
|
44
|
+
Client.stub(:get).with("/notifications/#{notification_details['id']}/member").and_return user_payload
|
45
|
+
@notification.member.id.should == user_details['id']
|
46
|
+
end
|
47
|
+
|
48
|
+
it "can retrieve the member creator" do
|
49
|
+
Client.stub(:get).with("/members/#{user_details['id']}").and_return user_payload
|
50
|
+
@notification.member_creator.id.should == user_details['id']
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "organization" do
|
55
|
+
it "can retrieve the organization" do
|
56
|
+
Client.stub(:get).with("/notifications/#{notification_details['id']}/organization").and_return JSON.generate(orgs_details.first)
|
57
|
+
@notification.organization.id.should == orgs_details.first['id']
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "local" do
|
62
|
+
it "gets the read status" do
|
63
|
+
@notification.unread?.should == notification_details['unread']
|
64
|
+
end
|
65
|
+
|
66
|
+
it "gets the type" do
|
67
|
+
@notification.type.should == notification_details['type']
|
68
|
+
end
|
69
|
+
|
70
|
+
it "gets the date" do
|
71
|
+
@notification.date.should == notification_details['date']
|
72
|
+
end
|
73
|
+
|
74
|
+
it "gets the data" do
|
75
|
+
@notification.data.should == notification_details['data']
|
76
|
+
end
|
77
|
+
|
78
|
+
it "gets the member creator id" do
|
79
|
+
@notification.member_creator_id.should == notification_details['idMemberCreator']
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
include Trello::Authorization
|
4
|
+
include Trello
|
5
|
+
|
6
|
+
describe OAuthPolicy do
|
7
|
+
before do
|
8
|
+
OAuthPolicy.consumer_credential = OAuthCredential.new "xxx", "xxx"
|
9
|
+
OAuthPolicy.token = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
context "2-legged" do
|
13
|
+
it "adds an authorization header" do
|
14
|
+
uri = Addressable::URI.parse("https://xxx/")
|
15
|
+
|
16
|
+
request = Request.new :get, uri
|
17
|
+
|
18
|
+
OAuthPolicy.token = OAuthCredential.new "token", nil
|
19
|
+
|
20
|
+
authorized_request = OAuthPolicy.authorize request
|
21
|
+
|
22
|
+
authorized_request.headers.keys.should include "Authorization"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "preserves query parameters" do
|
26
|
+
uri = Addressable::URI.parse("https://xxx/?name=Riccardo")
|
27
|
+
request = Request.new :get, uri
|
28
|
+
|
29
|
+
Clock.stub(:timestamp).and_return "1327048592"
|
30
|
+
Nonce.stub(:next).and_return "b94ff2bf7f0a5e87a326064ae1dbb18f"
|
31
|
+
OAuthPolicy.consumer_credential = OAuthCredential.new "consumer_key", "consumer_secret"
|
32
|
+
OAuthPolicy.token = OAuthCredential.new "token", nil
|
33
|
+
|
34
|
+
authorized_request = OAuthPolicy.authorize request
|
35
|
+
|
36
|
+
the_query_parameters = Addressable::URI.parse(authorized_request.uri).query_values
|
37
|
+
the_query_parameters.should == {"name" => "Riccardo"}
|
38
|
+
end
|
39
|
+
|
40
|
+
it "adds the correct signature as part of authorization header" do
|
41
|
+
Clock.stub(:timestamp).and_return "1327048592"
|
42
|
+
Nonce.stub(:next).and_return "b94ff2bf7f0a5e87a326064ae1dbb18f"
|
43
|
+
|
44
|
+
OAuthPolicy.consumer_credential = OAuthCredential.new "consumer_key", "consumer_secret"
|
45
|
+
OAuthPolicy.token = OAuthCredential.new "token", nil
|
46
|
+
|
47
|
+
request = Request.new :get, Addressable::URI.parse("http://xxx/")
|
48
|
+
|
49
|
+
authorized_request = OAuthPolicy.authorize request
|
50
|
+
|
51
|
+
authorized_request.headers["Authorization"].should =~ /oauth_signature="kLcSxrCTd4ATHcLmTp8q%2Foa%2BFMA%3D"/
|
52
|
+
end
|
53
|
+
|
54
|
+
it "adds correct signature for uri with parameters" do
|
55
|
+
Clock.stub(:timestamp).and_return "1327351010"
|
56
|
+
Nonce.stub(:next).and_return "f5474aaf44ca84df0b09870044f91c69"
|
57
|
+
|
58
|
+
OAuthPolicy.consumer_credential = OAuthCredential.new "consumer_key", "consumer_secret"
|
59
|
+
OAuthPolicy.token = OAuthCredential.new "token", nil
|
60
|
+
|
61
|
+
request = Request.new :get, Addressable::URI.parse("http://xxx/?a=b")
|
62
|
+
|
63
|
+
authorized_request = OAuthPolicy.authorize request
|
64
|
+
|
65
|
+
authorized_request.headers["Authorization"].should =~ /oauth_signature="xm%2FJ1swxxPb6mnuR1Q1ucJMdGRk%3D"/
|
66
|
+
end
|
67
|
+
|
68
|
+
it "fails if consumer_credential is unset" do
|
69
|
+
OAuthPolicy.consumer_credential = nil
|
70
|
+
|
71
|
+
request = Request.new :get, Addressable::URI.parse("http://xxx/")
|
72
|
+
|
73
|
+
lambda{OAuthPolicy.authorize request}.should raise_error "The consumer_credential has not been supplied."
|
74
|
+
end
|
75
|
+
|
76
|
+
it "can sign with token" do
|
77
|
+
Clock.stub(:timestamp).and_return "1327360530"
|
78
|
+
Nonce.stub(:next).and_return "4f610cb28e7aa8711558de5234af1f0e"
|
79
|
+
|
80
|
+
OAuthPolicy.consumer_credential = OAuthCredential.new "consumer_key", "consumer_secret"
|
81
|
+
OAuthPolicy.token = OAuthCredential.new "token_key", "token_secret"
|
82
|
+
|
83
|
+
request = Request.new :get, Addressable::URI.parse("http://xxx/")
|
84
|
+
|
85
|
+
authorized_request = OAuthPolicy.authorize request
|
86
|
+
|
87
|
+
authorized_request.headers["Authorization"].should =~ /oauth_signature="3JeZSzsLCYnGNdVALZMgbzQKN44%3D"/
|
88
|
+
end
|
89
|
+
|
90
|
+
it "adds correct signature for https uri"
|
91
|
+
it "adds correct signature for verbs other than get"
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
module Trello
|
5
|
+
describe Organization do
|
6
|
+
include Helpers
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
Client.stub(:get).with("/organizations/4ee7e59ae582acdec8000291").
|
10
|
+
and_return organization_payload
|
11
|
+
|
12
|
+
@organization = Organization.find('4ee7e59ae582acdec8000291')
|
13
|
+
end
|
14
|
+
|
15
|
+
context "actions" do
|
16
|
+
it "retrieves actions" do
|
17
|
+
Client.stub(:get).with("/organizations/4ee7e59ae582acdec8000291/actions", { :filter => :all }).and_return actions_payload
|
18
|
+
@organization.actions.count.should be > 0
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|