ruby-trello 0.4.4.3 → 0.5.0
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/README.md +81 -8
- data/lib/trello.rb +25 -9
- data/lib/trello/action.rb +5 -5
- data/lib/trello/association_proxy.rb +3 -3
- data/lib/trello/authorization.rb +105 -49
- data/lib/trello/basic_data.rb +48 -4
- data/lib/trello/board.rb +10 -9
- data/lib/trello/card.rb +38 -35
- data/lib/trello/checklist.rb +10 -8
- data/lib/trello/client.rb +98 -29
- data/lib/trello/configuration.rb +68 -0
- data/lib/trello/has_actions.rb +1 -1
- data/lib/trello/list.rb +9 -7
- data/lib/trello/member.rb +3 -3
- data/lib/trello/multi_association.rb +4 -2
- data/lib/trello/notification.rb +8 -8
- data/lib/trello/organization.rb +3 -3
- data/lib/trello/token.rb +4 -4
- data/spec/action_spec.rb +30 -18
- data/spec/basic_auth_policy_spec.rb +1 -0
- data/spec/board_spec.rb +141 -120
- data/spec/card_spec.rb +104 -82
- data/spec/checklist_spec.rb +35 -6
- data/spec/client_spec.rb +56 -19
- data/spec/configuration_spec.rb +114 -0
- data/spec/integration/how_to_authorize_spec.rb +1 -1
- data/spec/list_spec.rb +74 -20
- data/spec/member_spec.rb +37 -23
- data/spec/notification_spec.rb +28 -24
- data/spec/oauth_policy_spec.rb +55 -9
- data/spec/organization_spec.rb +18 -7
- data/spec/spec_helper.rb +5 -0
- data/spec/token_spec.rb +25 -8
- data/spec/trello_spec.rb +73 -0
- metadata +10 -6
@@ -0,0 +1,114 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Trello::Configuration do
|
4
|
+
let(:configuration) { Trello::Configuration.new }
|
5
|
+
|
6
|
+
it "has a consumer_key attribute" do
|
7
|
+
configuration.consumer_key = 'consumer_key'
|
8
|
+
configuration.consumer_key.should eq('consumer_key')
|
9
|
+
end
|
10
|
+
|
11
|
+
it "has a consumer_secret attribute" do
|
12
|
+
configuration.consumer_secret = 'consumer_secret'
|
13
|
+
configuration.consumer_secret.should eq('consumer_secret')
|
14
|
+
end
|
15
|
+
|
16
|
+
it "has a oauth_token attribute" do
|
17
|
+
configuration.oauth_token = 'oauth_token'
|
18
|
+
configuration.oauth_token.should eq('oauth_token')
|
19
|
+
end
|
20
|
+
|
21
|
+
it "has a oauth_token_secret attribute" do
|
22
|
+
configuration.oauth_token_secret = 'oauth_token_secret'
|
23
|
+
configuration.oauth_token_secret.should eq('oauth_token_secret')
|
24
|
+
end
|
25
|
+
|
26
|
+
it "has a developer public key attribute" do
|
27
|
+
configuration.developer_public_key = 'developer_public_key'
|
28
|
+
configuration.developer_public_key.should eq('developer_public_key')
|
29
|
+
end
|
30
|
+
|
31
|
+
it "has a member token attribute" do
|
32
|
+
configuration.member_token = 'member_token'
|
33
|
+
configuration.member_token.should eq('member_token')
|
34
|
+
end
|
35
|
+
|
36
|
+
it "has a callback (for oauth)" do
|
37
|
+
callback = lambda { 'foobar' }
|
38
|
+
configuration.callback = callback
|
39
|
+
configuration.callback.call.should eq('foobar')
|
40
|
+
end
|
41
|
+
|
42
|
+
it "has a return_url" do
|
43
|
+
configuration.return_url = "http://www.example.com/callback"
|
44
|
+
configuration.return_url.should eq("http://www.example.com/callback")
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "initialize" do
|
48
|
+
it "sets key attributes provided as a hash" do
|
49
|
+
configuration = Trello::Configuration.new(
|
50
|
+
:consumer_key => 'consumer_key',
|
51
|
+
:consumer_secret => 'consumer_secret',
|
52
|
+
:oauth_token => 'oauth_token',
|
53
|
+
:oauth_token_secret => 'oauth_token_secret'
|
54
|
+
)
|
55
|
+
configuration.consumer_key.should eq('consumer_key')
|
56
|
+
configuration.consumer_secret.should eq('consumer_secret')
|
57
|
+
configuration.oauth_token.should eq('oauth_token')
|
58
|
+
configuration.oauth_token_secret.should eq('oauth_token_secret')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#credentials" do
|
63
|
+
let(:configuration) { Trello::Configuration.new(attributes) }
|
64
|
+
|
65
|
+
it "returns an empty if no attributes specified" do
|
66
|
+
Trello::Configuration.new({}).credentials.should eq({})
|
67
|
+
end
|
68
|
+
|
69
|
+
it "returns an empty if attributes incomplete" do
|
70
|
+
Trello::Configuration.new(:consumer_key => 'consumer_key').credentials.should eq({})
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'returns a hash of oauth attributes' do
|
74
|
+
configuration = Trello::Configuration.new(
|
75
|
+
:consumer_key => 'consumer_key',
|
76
|
+
:consumer_secret => 'consumer_secret',
|
77
|
+
:oauth_token => 'oauth_token',
|
78
|
+
:oauth_token_secret => 'oauth_token_secret'
|
79
|
+
)
|
80
|
+
configuration.credentials.should eq(
|
81
|
+
:consumer_key => 'consumer_key',
|
82
|
+
:consumer_secret => 'consumer_secret',
|
83
|
+
:oauth_token => 'oauth_token',
|
84
|
+
:oauth_token_secret => 'oauth_token_secret'
|
85
|
+
)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'includes callback and return url if given' do
|
89
|
+
configuration = Trello::Configuration.new(
|
90
|
+
:consumer_key => 'consumer_key',
|
91
|
+
:consumer_secret => 'consumer_secret',
|
92
|
+
:return_url => 'http://example.com',
|
93
|
+
:callback => 'callback'
|
94
|
+
)
|
95
|
+
configuration.credentials.should eq(
|
96
|
+
:consumer_key => 'consumer_key',
|
97
|
+
:consumer_secret => 'consumer_secret',
|
98
|
+
:return_url => 'http://example.com',
|
99
|
+
:callback => 'callback'
|
100
|
+
)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "returns a hash of basic auth policy attributes" do
|
104
|
+
configuration = Trello::Configuration.new(
|
105
|
+
:developer_public_key => 'developer_public_key',
|
106
|
+
:member_token => 'member_token'
|
107
|
+
)
|
108
|
+
configuration.credentials.should eq(
|
109
|
+
:developer_public_key => 'developer_public_key',
|
110
|
+
:member_token => 'member_token'
|
111
|
+
)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -45,7 +45,7 @@ describe "OAuth", :broken => true do
|
|
45
45
|
it "[!] actually does not enforce signature at all, only the keys are required" do
|
46
46
|
OAuthPolicy.consumer_credential = OAuthCredential.new @developer_public_key, nil
|
47
47
|
OAuthPolicy.token = OAuthCredential.new @access_token_key, nil
|
48
|
-
|
48
|
+
|
49
49
|
pending "I would expect this to fail because I have signed with nil secrets" do
|
50
50
|
lambda{Client.get("/boards/#{@welcome_board}/")}.should raise_error
|
51
51
|
end
|
data/spec/list_spec.rb
CHANGED
@@ -4,11 +4,61 @@ module Trello
|
|
4
4
|
describe List do
|
5
5
|
include Helpers
|
6
6
|
|
7
|
+
let(:list) { client.find(:list, "abcdef123456789123456789") }
|
8
|
+
let(:client) { Client.new }
|
9
|
+
|
7
10
|
before(:each) do
|
8
|
-
|
9
|
-
|
11
|
+
client.stub(:get).with("/lists/abcdef123456789123456789").and_return JSON.generate(lists_details.first)
|
12
|
+
client.stub(:get).with("/boards/abcdef123456789123456789").and_return JSON.generate(boards_details.first)
|
13
|
+
end
|
10
14
|
|
11
|
-
|
15
|
+
context "finding" do
|
16
|
+
let(:client) { Trello.client }
|
17
|
+
|
18
|
+
it "delegates to client#find" do
|
19
|
+
client.should_receive(:find).with(:list, 'abcdef123456789123456789')
|
20
|
+
List.find('abcdef123456789123456789')
|
21
|
+
end
|
22
|
+
|
23
|
+
it "is equivalent to client#find" do
|
24
|
+
List.find('abcdef123456789123456789').should eq(list)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "creating" do
|
29
|
+
let(:client) { Trello.client }
|
30
|
+
|
31
|
+
it "creates a new record" do
|
32
|
+
list = List.new(lists_details.first)
|
33
|
+
list.should be_valid
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'must not be valid if not given a name' do
|
37
|
+
list = List.new(lists_details.first.except('name'))
|
38
|
+
list.should_not be_valid
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'must not be valid if not given a list id' do
|
42
|
+
list = List.new(lists_details.first.except('id'))
|
43
|
+
list.should_not be_valid
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'creates a new record and saves it on Trello', :refactor => true do
|
47
|
+
payload = {
|
48
|
+
:name => 'Test List',
|
49
|
+
:board_id => 'abcdef123456789123456789'
|
50
|
+
}
|
51
|
+
|
52
|
+
result = JSON.generate(payload)
|
53
|
+
|
54
|
+
expected_payload = {:name => "Test List", :closed => false, :idBoard => "abcdef123456789123456789"}
|
55
|
+
|
56
|
+
client.should_receive(:post).with("/lists", expected_payload).and_return result
|
57
|
+
|
58
|
+
list = List.create(payload)
|
59
|
+
|
60
|
+
list.class.should be List
|
61
|
+
end
|
12
62
|
end
|
13
63
|
|
14
64
|
context "updating" do
|
@@ -20,65 +70,69 @@ module Trello
|
|
20
70
|
:closed => false
|
21
71
|
}
|
22
72
|
|
23
|
-
|
24
|
-
|
25
|
-
|
73
|
+
client.should_receive(:put).once.with("/lists/abcdef123456789123456789", payload)
|
74
|
+
list.name = expected_new_name
|
75
|
+
list.save
|
26
76
|
end
|
27
77
|
end
|
28
78
|
|
29
79
|
context "fields" do
|
30
80
|
it "gets its id" do
|
31
|
-
|
81
|
+
list.id.should == lists_details.first['id']
|
32
82
|
end
|
33
83
|
|
34
84
|
it "gets its name" do
|
35
|
-
|
85
|
+
list.name.should == lists_details.first['name']
|
36
86
|
end
|
37
87
|
|
38
88
|
it "knows if it is open or closed" do
|
39
|
-
|
89
|
+
list.closed.should == lists_details.first['closed']
|
40
90
|
end
|
41
91
|
|
42
92
|
it "has a board" do
|
43
|
-
|
93
|
+
list.board.should == Board.new(boards_details.first)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "gets its position" do
|
97
|
+
list.pos.should == lists_details.first['pos']
|
44
98
|
end
|
45
99
|
end
|
46
100
|
|
47
101
|
context "actions" do
|
48
102
|
it "has a list of actions" do
|
49
|
-
|
50
|
-
|
103
|
+
client.stub(:get).with("/lists/abcdef123456789123456789/actions", { :filter => :all }).and_return actions_payload
|
104
|
+
list.actions.count.should be > 0
|
51
105
|
end
|
52
106
|
end
|
53
107
|
|
54
108
|
context "cards" do
|
55
109
|
it "has a list of cards" do
|
56
|
-
|
57
|
-
|
110
|
+
client.stub(:get).with("/lists/abcdef123456789123456789/cards", { :filter => :open }).and_return cards_payload
|
111
|
+
list.cards.count.should be > 0
|
58
112
|
end
|
59
113
|
end
|
60
114
|
|
61
115
|
describe "#closed?" do
|
62
116
|
it "returns the closed attribute" do
|
63
|
-
|
117
|
+
list.closed?.should_not be_true
|
64
118
|
end
|
65
119
|
end
|
66
120
|
|
67
121
|
describe "#close" do
|
68
122
|
it "updates the close attribute to true" do
|
69
|
-
|
70
|
-
|
123
|
+
list.close
|
124
|
+
list.closed.should be_true
|
71
125
|
end
|
72
126
|
end
|
73
127
|
|
74
128
|
describe "#close!" do
|
75
129
|
it "updates the close attribute to true and saves the list" do
|
76
|
-
|
77
|
-
:name =>
|
130
|
+
client.should_receive(:put).once.with("/lists/abcdef123456789123456789", {
|
131
|
+
:name => list.name,
|
78
132
|
:closed => true
|
79
133
|
})
|
80
134
|
|
81
|
-
|
135
|
+
list.close!
|
82
136
|
end
|
83
137
|
end
|
84
138
|
end
|
data/spec/member_spec.rb
CHANGED
@@ -6,86 +6,100 @@ module Trello
|
|
6
6
|
describe Member do
|
7
7
|
include Helpers
|
8
8
|
|
9
|
+
let(:member) { client.find(:member, 'abcdef123456789012345678') }
|
10
|
+
let(:client) { Client.new }
|
11
|
+
|
9
12
|
before(:each) do
|
10
|
-
|
13
|
+
client.stub(:get).with("/members/abcdef123456789012345678").and_return user_payload
|
14
|
+
end
|
15
|
+
|
16
|
+
context "finding" do
|
17
|
+
let(:client) { Trello.client }
|
11
18
|
|
12
|
-
|
19
|
+
it "delegates to Trello.client#find" do
|
20
|
+
client.should_receive(:find).with(:member, 'abcdef123456789012345678')
|
21
|
+
Member.find('abcdef123456789012345678')
|
22
|
+
end
|
23
|
+
|
24
|
+
it "is equivalent to client#find" do
|
25
|
+
Member.find('abcdef123456789012345678').should eq(member)
|
26
|
+
end
|
13
27
|
end
|
14
28
|
|
15
29
|
context "actions" do
|
16
30
|
it "retrieves a list of actions", :refactor => true do
|
17
|
-
|
18
|
-
|
31
|
+
client.stub(:get).with("/members/abcdef123456789012345678/actions", { :filter => :all }).and_return actions_payload
|
32
|
+
member.actions.count.should be > 0
|
19
33
|
end
|
20
34
|
end
|
21
35
|
|
22
36
|
context "boards" do
|
23
37
|
it "has a list of boards" do
|
24
|
-
|
25
|
-
boards =
|
38
|
+
client.stub(:get).with("/members/abcdef123456789012345678/boards", { :filter => :all }).and_return boards_payload
|
39
|
+
boards = member.boards
|
26
40
|
boards.count.should be > 0
|
27
41
|
end
|
28
42
|
end
|
29
43
|
|
30
44
|
context "cards" do
|
31
45
|
it "has a list of cards" do
|
32
|
-
|
33
|
-
cards =
|
46
|
+
client.stub(:get).with("/members/abcdef123456789012345678/cards", { :filter => :open }).and_return cards_payload
|
47
|
+
cards = member.cards
|
34
48
|
cards.count.should be > 0
|
35
49
|
end
|
36
50
|
end
|
37
51
|
|
38
52
|
context "organizations" do
|
39
53
|
it "has a list of organizations" do
|
40
|
-
|
41
|
-
orgs =
|
54
|
+
client.stub(:get).with("/members/abcdef123456789012345678/organizations", { :filter => :all }).and_return orgs_payload
|
55
|
+
orgs = member.organizations
|
42
56
|
orgs.count.should be > 0
|
43
57
|
end
|
44
58
|
end
|
45
59
|
|
46
60
|
context "notifications" do
|
47
61
|
it "has a list of notifications" do
|
48
|
-
|
49
|
-
|
62
|
+
client.stub(:get).with("/members/abcdef123456789012345678/notifications", {}).and_return "[" << notification_payload << "]"
|
63
|
+
member.notifications.count.should be 1
|
50
64
|
end
|
51
65
|
end
|
52
66
|
|
53
67
|
context "personal" do
|
54
68
|
it "gets the members bio" do
|
55
|
-
|
69
|
+
member.bio.should == user_details['bio']
|
56
70
|
end
|
57
71
|
|
58
72
|
it "gets the full name" do
|
59
|
-
|
73
|
+
member.full_name.should == user_details['fullName']
|
60
74
|
end
|
61
75
|
|
62
76
|
it "gets the avatar id" do
|
63
|
-
|
77
|
+
member.avatar_id.should == user_details['avatarHash']
|
64
78
|
end
|
65
79
|
|
66
80
|
it "returns a valid url for the avatar" do
|
67
|
-
|
68
|
-
|
81
|
+
member.avatar_url(:size => :large).should == "https://trello-avatars.s3.amazonaws.com/abcdef1234567890abcdef1234567890/170.png"
|
82
|
+
member.avatar_url(:size => :small).should == "https://trello-avatars.s3.amazonaws.com/abcdef1234567890abcdef1234567890/30.png"
|
69
83
|
end
|
70
84
|
|
71
85
|
it "gets the url" do
|
72
|
-
|
86
|
+
member.url.should == user_details['url']
|
73
87
|
end
|
74
88
|
|
75
89
|
it "gets the username" do
|
76
|
-
|
90
|
+
member.username.should == user_details['username']
|
77
91
|
end
|
78
92
|
end
|
79
93
|
|
80
94
|
context "modification" do
|
81
95
|
it "lets us know a field has changed without committing it" do
|
82
|
-
|
83
|
-
|
84
|
-
|
96
|
+
member.changed?.should be_false
|
97
|
+
member.bio = "New and amazing"
|
98
|
+
member.changed?.should be_true
|
85
99
|
end
|
86
100
|
|
87
101
|
it "doesn't understand the #id= method" do
|
88
|
-
lambda {
|
102
|
+
lambda { member.id = "42" }.should raise_error NoMethodError
|
89
103
|
end
|
90
104
|
end
|
91
105
|
end
|
data/spec/notification_spec.rb
CHANGED
@@ -4,80 +4,84 @@ module Trello
|
|
4
4
|
describe Notification do
|
5
5
|
include Helpers
|
6
6
|
|
7
|
+
let(:notification) { member.notifications.first }
|
8
|
+
let(:member) { client.find(:member, "abcdef123456789012345678") }
|
9
|
+
let(:client) { Client.new }
|
10
|
+
|
7
11
|
before(:each) do
|
8
|
-
|
9
|
-
|
10
|
-
Client.stub(:get).with("/members/abcdef123456789012345678/notifications", {}).and_return "[" << notification_payload << "]"
|
11
|
-
@notification = member.notifications.first
|
12
|
+
client.stub(:get).with("/members/abcdef123456789012345678").and_return user_payload
|
13
|
+
client.stub(:get).with("/members/abcdef123456789012345678/notifications", {}).and_return "[" << notification_payload << "]"
|
12
14
|
end
|
13
15
|
|
14
16
|
context "finding" do
|
17
|
+
let(:client) { Trello.client }
|
18
|
+
|
15
19
|
it "can find a specific notification" do
|
16
|
-
|
17
|
-
Notification.find(notification_details['id']).should ==
|
20
|
+
client.stub(:get).with("/notifications/#{notification_details['id']}").and_return notification_payload
|
21
|
+
Notification.find(notification_details['id']).should == notification
|
18
22
|
end
|
19
23
|
end
|
20
24
|
|
21
25
|
context "boards" do
|
22
26
|
it "can retrieve the board" do
|
23
|
-
|
24
|
-
|
27
|
+
client.stub(:get).with("/notifications/#{notification_details['id']}/board").and_return JSON.generate(boards_details.first)
|
28
|
+
notification.board.id.should == boards_details.first['id']
|
25
29
|
end
|
26
30
|
end
|
27
31
|
|
28
32
|
context "lists" do
|
29
33
|
it "can retrieve the list" do
|
30
|
-
|
31
|
-
|
34
|
+
client.stub(:get).with("/notifications/#{notification_details['id']}/list").and_return JSON.generate(lists_details.first)
|
35
|
+
notification.list.id.should == lists_details.first['id']
|
32
36
|
end
|
33
37
|
end
|
34
38
|
|
35
39
|
context "cards" do
|
36
40
|
it "can retrieve the card" do
|
37
|
-
|
38
|
-
|
41
|
+
client.stub(:get).with("/notifications/#{notification_details['id']}/card").and_return JSON.generate(cards_details.first)
|
42
|
+
notification.card.id.should == cards_details.first['id']
|
39
43
|
end
|
40
44
|
end
|
41
45
|
|
42
46
|
context "members" do
|
43
47
|
it "can retrieve the member" do
|
44
|
-
|
45
|
-
|
48
|
+
client.stub(:get).with("/notifications/#{notification_details['id']}/member").and_return user_payload
|
49
|
+
notification.member.id.should == user_details['id']
|
46
50
|
end
|
47
51
|
|
48
52
|
it "can retrieve the member creator" do
|
49
|
-
|
50
|
-
|
53
|
+
client.stub(:get).with("/members/#{user_details['id']}").and_return user_payload
|
54
|
+
notification.member_creator.id.should == user_details['id']
|
51
55
|
end
|
52
56
|
end
|
53
57
|
|
54
58
|
context "organization" do
|
55
59
|
it "can retrieve the organization" do
|
56
|
-
|
57
|
-
|
60
|
+
client.stub(:get).with("/notifications/#{notification_details['id']}/organization").and_return JSON.generate(orgs_details.first)
|
61
|
+
notification.organization.id.should == orgs_details.first['id']
|
58
62
|
end
|
59
63
|
end
|
60
64
|
|
61
65
|
context "local" do
|
62
66
|
it "gets the read status" do
|
63
|
-
|
67
|
+
notification.unread?.should == notification_details['unread']
|
64
68
|
end
|
65
69
|
|
66
70
|
it "gets the type" do
|
67
|
-
|
71
|
+
notification.type.should == notification_details['type']
|
68
72
|
end
|
69
73
|
|
70
74
|
it "gets the date" do
|
71
|
-
|
75
|
+
notification.date.should == notification_details['date']
|
72
76
|
end
|
73
77
|
|
74
78
|
it "gets the data" do
|
75
|
-
|
79
|
+
notification.data.should == notification_details['data']
|
76
80
|
end
|
77
81
|
|
78
82
|
it "gets the member creator id" do
|
79
|
-
|
83
|
+
notification.member_creator_id.should == notification_details['idMemberCreator']
|
80
84
|
end
|
81
85
|
end
|
82
86
|
end
|
83
|
-
end
|
87
|
+
end
|