ruby-trello 1.2.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -5
- data/lib/trello/board.rb +6 -8
- data/lib/trello/card.rb +14 -28
- data/lib/trello/checklist.rb +14 -0
- data/lib/trello/item.rb +4 -0
- data/lib/trello/label.rb +3 -3
- data/lib/trello/list.rb +13 -3
- data/lib/trello/organization.rb +14 -7
- data/spec/action_spec.rb +67 -31
- data/spec/array_spec.rb +1 -1
- data/spec/association_spec.rb +11 -7
- data/spec/basic_auth_policy_spec.rb +4 -4
- data/spec/board_spec.rb +169 -92
- data/spec/card_spec.rb +232 -119
- data/spec/checklist_spec.rb +109 -16
- data/spec/client_spec.rb +83 -45
- data/spec/configuration_spec.rb +24 -43
- data/spec/hash_spec.rb +5 -1
- data/spec/item_spec.rb +27 -9
- data/spec/label_spec.rb +52 -27
- data/spec/list_spec.rb +86 -29
- data/spec/member_spec.rb +62 -40
- data/spec/notification_spec.rb +57 -22
- data/spec/oauth_policy_spec.rb +45 -24
- data/spec/organization_spec.rb +16 -8
- data/spec/spec_helper.rb +28 -3
- data/spec/string_spec.rb +11 -8
- data/spec/token_spec.rb +31 -11
- data/spec/trello_spec.rb +20 -23
- data/spec/webhook_spec.rb +24 -9
- metadata +4 -6
- data/spec/item_state_spec.rb +0 -0
data/spec/member_spec.rb
CHANGED
@@ -9,105 +9,127 @@ module Trello
|
|
9
9
|
let(:member) { client.find(:member, 'abcdef123456789012345678') }
|
10
10
|
let(:client) { Client.new }
|
11
11
|
|
12
|
-
before
|
13
|
-
client
|
12
|
+
before do
|
13
|
+
allow(client)
|
14
|
+
.to receive(:get)
|
15
|
+
.with('/members/abcdef123456789012345678', {})
|
16
|
+
.and_return user_payload
|
14
17
|
end
|
15
18
|
|
16
19
|
context 'finding' do
|
17
20
|
let(:client) { Trello.client }
|
18
21
|
|
19
22
|
it 'delegates to Trello.client#find' do
|
20
|
-
client
|
23
|
+
expect(client)
|
24
|
+
.to receive(:find)
|
25
|
+
.with(:member, 'abcdef123456789012345678', {})
|
26
|
+
|
21
27
|
Member.find('abcdef123456789012345678')
|
22
28
|
end
|
23
29
|
|
24
30
|
it 'is equivalent to client#find' do
|
25
|
-
Member.find('abcdef123456789012345678').
|
31
|
+
expect(Member.find('abcdef123456789012345678')).to eq(member)
|
26
32
|
end
|
27
33
|
end
|
28
34
|
|
29
|
-
|
30
|
-
|
31
|
-
client
|
32
|
-
|
35
|
+
describe 'attributes' do
|
36
|
+
before do
|
37
|
+
allow(client)
|
38
|
+
.to receive(:get)
|
39
|
+
.with("/members/abcdef123456789012345678/#{resource}", { filter: filter })
|
40
|
+
.and_return payload
|
33
41
|
end
|
34
|
-
end
|
35
42
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
43
|
+
describe 'actions' do
|
44
|
+
let(:resource) { 'actions' }
|
45
|
+
let(:filter) { :all }
|
46
|
+
let(:payload) { actions_payload }
|
47
|
+
|
48
|
+
it 'retrieves a list of actions' do
|
49
|
+
expect(member.actions.count).to be > 0
|
50
|
+
end
|
41
51
|
end
|
42
|
-
end
|
43
52
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
53
|
+
describe 'boards' do
|
54
|
+
let(:resource) { 'boards' }
|
55
|
+
let(:filter) { :all }
|
56
|
+
let(:payload) { boards_payload }
|
57
|
+
|
58
|
+
it { expect(member.boards.count).to be > 0 }
|
49
59
|
end
|
50
|
-
end
|
51
60
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
61
|
+
describe 'cards' do
|
62
|
+
let(:resource) { 'cards' }
|
63
|
+
let(:filter) { :open }
|
64
|
+
let(:payload) { cards_payload }
|
65
|
+
|
66
|
+
it { expect(member.cards.count).to be > 0 }
|
67
|
+
end
|
68
|
+
|
69
|
+
describe 'organizations' do
|
70
|
+
let(:resource) { 'organizations' }
|
71
|
+
let(:filter) { :all }
|
72
|
+
let(:payload) { orgs_payload }
|
73
|
+
|
74
|
+
it { expect(member.organizations.count).to be > 0 }
|
57
75
|
end
|
58
76
|
end
|
59
77
|
|
60
78
|
context 'notifications' do
|
61
79
|
it 'has a list of notifications' do
|
62
|
-
client
|
63
|
-
|
80
|
+
allow(client)
|
81
|
+
.to receive(:get)
|
82
|
+
.with('/members/abcdef123456789012345678/notifications', {})
|
83
|
+
.and_return '[' << notification_payload << ']'
|
84
|
+
|
85
|
+
expect(member.notifications.count).to eq 1
|
64
86
|
end
|
65
87
|
end
|
66
88
|
|
67
89
|
context 'personal' do
|
68
90
|
it 'gets the members bio' do
|
69
|
-
member.bio.
|
91
|
+
expect(member.bio).to eq user_details['bio']
|
70
92
|
end
|
71
93
|
|
72
94
|
it 'gets the full name' do
|
73
|
-
member.full_name.
|
95
|
+
expect(member.full_name).to eq user_details['fullName']
|
74
96
|
end
|
75
97
|
|
76
98
|
it 'gets the avatar id' do
|
77
|
-
member.avatar_id.
|
99
|
+
expect(member.avatar_id).to eq user_details['avatarHash']
|
78
100
|
end
|
79
101
|
|
80
102
|
it 'returns a valid url for the avatar' do
|
81
|
-
member.avatar_url(size: :large).
|
82
|
-
member.avatar_url(size: :small).
|
103
|
+
expect(member.avatar_url(size: :large)).to eq 'https://trello-avatars.s3.amazonaws.com/abcdef1234567890abcdef1234567890/170.png'
|
104
|
+
expect(member.avatar_url(size: :small)).to eq 'https://trello-avatars.s3.amazonaws.com/abcdef1234567890abcdef1234567890/30.png'
|
83
105
|
end
|
84
106
|
|
85
107
|
it 'gets the url' do
|
86
|
-
member.url.
|
108
|
+
expect(member.url).to eq user_details['url']
|
87
109
|
end
|
88
110
|
|
89
111
|
it 'gets the username' do
|
90
|
-
member.username.
|
112
|
+
expect(member.username).to eq user_details['username']
|
91
113
|
end
|
92
114
|
|
93
115
|
it 'gets the email' do
|
94
|
-
member.email.
|
116
|
+
expect(member.email).to eq user_details['email']
|
95
117
|
end
|
96
118
|
|
97
119
|
it 'gets the initials' do
|
98
|
-
member.initials.
|
120
|
+
expect(member.initials).to eq user_details['initials']
|
99
121
|
end
|
100
122
|
end
|
101
123
|
|
102
124
|
context 'modification' do
|
103
125
|
it 'lets us know a field has changed without committing it' do
|
104
|
-
expect(member
|
126
|
+
expect(member).to_not be_changed
|
105
127
|
member.bio = 'New and amazing'
|
106
|
-
expect(member
|
128
|
+
expect(member).to be_changed
|
107
129
|
end
|
108
130
|
|
109
131
|
it 'does not understand the #id= method' do
|
110
|
-
|
132
|
+
expect { member.id = '42' }.to raise_error NoMethodError
|
111
133
|
end
|
112
134
|
end
|
113
135
|
end
|
data/spec/notification_spec.rb
CHANGED
@@ -8,79 +8,114 @@ module Trello
|
|
8
8
|
let(:member) { client.find(:member, "abcdef123456789012345678") }
|
9
9
|
let(:client) { Client.new }
|
10
10
|
|
11
|
-
before
|
12
|
-
client
|
13
|
-
|
11
|
+
before do
|
12
|
+
allow(client)
|
13
|
+
.to receive(:get)
|
14
|
+
.with("/members/abcdef123456789012345678", {})
|
15
|
+
.and_return user_payload
|
16
|
+
|
17
|
+
allow(client)
|
18
|
+
.to receive(:get)
|
19
|
+
.with("/members/abcdef123456789012345678/notifications", {})
|
20
|
+
.and_return("[" << notification_payload << "]")
|
14
21
|
end
|
15
22
|
|
16
23
|
context "finding" do
|
17
24
|
let(:client) { Trello.client }
|
18
25
|
|
19
26
|
it "can find a specific notification" do
|
20
|
-
client
|
21
|
-
|
27
|
+
allow(client)
|
28
|
+
.to receive(:get)
|
29
|
+
.with("/notifications/#{notification_details['id']}", {})
|
30
|
+
.and_return notification_payload
|
31
|
+
|
32
|
+
expect(Notification.find(notification_details['id'])).to eq notification
|
22
33
|
end
|
23
34
|
end
|
24
35
|
|
25
36
|
context "boards" do
|
26
37
|
it "can retrieve the board" do
|
27
|
-
client
|
28
|
-
|
38
|
+
allow(client)
|
39
|
+
.to receive(:get)
|
40
|
+
.with("/notifications/#{notification_details['id']}/board")
|
41
|
+
.and_return JSON.generate(boards_details.first)
|
42
|
+
|
43
|
+
expect(notification.board.id).to eq boards_details.first['id']
|
29
44
|
end
|
30
45
|
end
|
31
46
|
|
32
47
|
context "lists" do
|
33
48
|
it "can retrieve the list" do
|
34
|
-
client
|
35
|
-
|
49
|
+
allow(client)
|
50
|
+
.to receive(:get)
|
51
|
+
.with("/notifications/#{notification_details['id']}/list")
|
52
|
+
.and_return JSON.generate(lists_details.first)
|
53
|
+
|
54
|
+
expect(notification.list.id).to eq lists_details.first['id']
|
36
55
|
end
|
37
56
|
end
|
38
57
|
|
39
58
|
context "cards" do
|
40
59
|
it "can retrieve the card" do
|
41
|
-
client
|
42
|
-
|
60
|
+
allow(client)
|
61
|
+
.to receive(:get)
|
62
|
+
.with("/notifications/#{notification_details['id']}/card")
|
63
|
+
.and_return JSON.generate(cards_details.first)
|
64
|
+
|
65
|
+
expect(notification.card.id).to eq cards_details.first['id']
|
43
66
|
end
|
44
67
|
end
|
45
68
|
|
46
69
|
context "members" do
|
47
70
|
it "can retrieve the member" do
|
48
|
-
client
|
49
|
-
|
71
|
+
allow(client)
|
72
|
+
.to receive(:get)
|
73
|
+
.with("/notifications/#{notification_details['id']}/member")
|
74
|
+
.and_return user_payload
|
75
|
+
|
76
|
+
expect(notification.member.id).to eq user_details['id']
|
50
77
|
end
|
51
78
|
|
52
79
|
it "can retrieve the member creator" do
|
53
|
-
client
|
54
|
-
|
80
|
+
allow(client)
|
81
|
+
.to receive(:get)
|
82
|
+
.with("/members/#{user_details['id']}", {})
|
83
|
+
.and_return user_payload
|
84
|
+
|
85
|
+
expect(notification.member_creator.id).to eq user_details['id']
|
55
86
|
end
|
56
87
|
end
|
57
88
|
|
58
89
|
context "organization" do
|
59
90
|
it "can retrieve the organization" do
|
60
|
-
client
|
61
|
-
|
91
|
+
allow(client)
|
92
|
+
.to receive(:get)
|
93
|
+
.with("/notifications/#{notification_details['id']}/organization")
|
94
|
+
.and_return JSON.generate(orgs_details.first)
|
95
|
+
|
96
|
+
expect(notification.organization.id).to eq orgs_details.first['id']
|
62
97
|
end
|
63
98
|
end
|
64
99
|
|
65
100
|
context "local" do
|
66
101
|
it "gets the read status" do
|
67
|
-
notification.unread
|
102
|
+
expect(notification.unread?).to eq notification_details['unread']
|
68
103
|
end
|
69
104
|
|
70
105
|
it "gets the type" do
|
71
|
-
notification.type.
|
106
|
+
expect(notification.type).to eq notification_details['type']
|
72
107
|
end
|
73
108
|
|
74
109
|
it "gets the date" do
|
75
|
-
notification.date.
|
110
|
+
expect(notification.date).to eq notification_details['date']
|
76
111
|
end
|
77
112
|
|
78
113
|
it "gets the data" do
|
79
|
-
notification.data.
|
114
|
+
expect(notification.data).to eq notification_details['data']
|
80
115
|
end
|
81
116
|
|
82
117
|
it "gets the member creator id" do
|
83
|
-
notification.member_creator_id.
|
118
|
+
expect(notification.member_creator_id).to eq notification_details['idMemberCreator']
|
84
119
|
end
|
85
120
|
end
|
86
121
|
end
|
data/spec/oauth_policy_spec.rb
CHANGED
@@ -12,8 +12,8 @@ describe OAuthPolicy do
|
|
12
12
|
describe '#consumer_credential' do
|
13
13
|
it 'uses class setting if available' do
|
14
14
|
policy = OAuthPolicy.new
|
15
|
-
policy.consumer_credential.key.
|
16
|
-
policy.consumer_credential.secret.
|
15
|
+
expect(policy.consumer_credential.key).to eq('xxx')
|
16
|
+
expect(policy.consumer_credential.secret).to eq('xxx')
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'is built from given consumer_key and consumer_secret' do
|
@@ -21,14 +21,14 @@ describe OAuthPolicy do
|
|
21
21
|
consumer_key: 'consumer_key',
|
22
22
|
consumer_secret: 'consumer_secret'
|
23
23
|
)
|
24
|
-
policy.consumer_credential.key.
|
25
|
-
policy.consumer_credential.secret.
|
24
|
+
expect(policy.consumer_credential.key).to eq('consumer_key')
|
25
|
+
expect(policy.consumer_credential.secret).to eq('consumer_secret')
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'is nil if none supplied to class' do
|
29
29
|
OAuthPolicy.consumer_credential = nil
|
30
30
|
policy = OAuthPolicy.new
|
31
|
-
policy.consumer_credential.
|
31
|
+
expect(policy.consumer_credential).to be_nil
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -36,8 +36,8 @@ describe OAuthPolicy do
|
|
36
36
|
it 'uses class setting if available' do
|
37
37
|
OAuthPolicy.token = OAuthCredential.new 'xxx', 'xxx'
|
38
38
|
policy = OAuthPolicy.new
|
39
|
-
policy.token.key.
|
40
|
-
policy.token.secret.
|
39
|
+
expect(policy.token.key).to eq('xxx')
|
40
|
+
expect(policy.token.secret).to eq('xxx')
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'is built from given oauth_token and oauth_token_secret' do
|
@@ -45,13 +45,13 @@ describe OAuthPolicy do
|
|
45
45
|
oauth_token: 'oauth_token',
|
46
46
|
oauth_token_secret: 'oauth_token_secret'
|
47
47
|
)
|
48
|
-
policy.token.key.
|
49
|
-
policy.token.secret.
|
48
|
+
expect(policy.token.key).to eq('oauth_token')
|
49
|
+
expect(policy.token.secret).to eq('oauth_token_secret')
|
50
50
|
end
|
51
51
|
|
52
52
|
it 'is an empty token if no oauth credentials supplied' do
|
53
53
|
policy = OAuthPolicy.new
|
54
|
-
policy.token.
|
54
|
+
expect(policy.token).to be_nil
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
@@ -65,27 +65,38 @@ describe OAuthPolicy do
|
|
65
65
|
|
66
66
|
authorized_request = OAuthPolicy.authorize request
|
67
67
|
|
68
|
-
authorized_request.headers.keys.
|
68
|
+
expect(authorized_request.headers.keys).to include 'Authorization'
|
69
69
|
end
|
70
70
|
|
71
71
|
it 'preserves query parameters' do
|
72
72
|
uri = Addressable::URI.parse('https://xxx/?name=Riccardo')
|
73
73
|
request = Request.new :get, uri
|
74
74
|
|
75
|
-
Clock
|
76
|
-
|
75
|
+
allow(Clock)
|
76
|
+
.to receive(:timestamp)
|
77
|
+
.and_return '1327048592'
|
78
|
+
|
79
|
+
allow(Nonce)
|
80
|
+
.to receive(:next)
|
81
|
+
.and_return 'b94ff2bf7f0a5e87a326064ae1dbb18f'
|
82
|
+
|
77
83
|
OAuthPolicy.consumer_credential = OAuthCredential.new 'consumer_key', 'consumer_secret'
|
78
84
|
OAuthPolicy.token = OAuthCredential.new 'token', nil
|
79
85
|
|
80
86
|
authorized_request = OAuthPolicy.authorize request
|
81
87
|
|
82
88
|
the_query_parameters = Addressable::URI.parse(authorized_request.uri).query_values
|
83
|
-
the_query_parameters.
|
89
|
+
expect(the_query_parameters).to eq({'name' => 'Riccardo'})
|
84
90
|
end
|
85
91
|
|
86
92
|
it 'adds the correct signature as part of authorization header' do
|
87
|
-
Clock
|
88
|
-
|
93
|
+
allow(Clock)
|
94
|
+
.to receive(:timestamp)
|
95
|
+
.and_return '1327048592'
|
96
|
+
|
97
|
+
allow(Nonce)
|
98
|
+
.to receive(:next)
|
99
|
+
.and_return 'b94ff2bf7f0a5e87a326064ae1dbb18f'
|
89
100
|
|
90
101
|
OAuthPolicy.consumer_credential = OAuthCredential.new 'consumer_key', 'consumer_secret'
|
91
102
|
OAuthPolicy.token = OAuthCredential.new 'token', nil
|
@@ -94,12 +105,17 @@ describe OAuthPolicy do
|
|
94
105
|
|
95
106
|
authorized_request = OAuthPolicy.authorize request
|
96
107
|
|
97
|
-
authorized_request.headers['Authorization'].
|
108
|
+
expect(authorized_request.headers['Authorization']).to match(/oauth_signature="TVNk%2FCs03FHqutDUqn05%2FDkvVek%3D"/)
|
98
109
|
end
|
99
110
|
|
100
111
|
it 'adds correct signature for uri with parameters' do
|
101
|
-
Clock
|
102
|
-
|
112
|
+
allow(Clock)
|
113
|
+
.to receive(:timestamp)
|
114
|
+
.and_return '1327351010'
|
115
|
+
|
116
|
+
allow(Nonce)
|
117
|
+
.to receive(:next)
|
118
|
+
.and_return 'f5474aaf44ca84df0b09870044f91c69'
|
103
119
|
|
104
120
|
OAuthPolicy.consumer_credential = OAuthCredential.new 'consumer_key', 'consumer_secret'
|
105
121
|
OAuthPolicy.token = OAuthCredential.new 'token', nil
|
@@ -108,7 +124,7 @@ describe OAuthPolicy do
|
|
108
124
|
|
109
125
|
authorized_request = OAuthPolicy.authorize request
|
110
126
|
|
111
|
-
authorized_request.headers['Authorization'].
|
127
|
+
expect(authorized_request.headers['Authorization']).to match(/oauth_signature="DprU1bdbNdJQ40UhD4n7wRR9jts%3D"/)
|
112
128
|
end
|
113
129
|
|
114
130
|
it 'fails if consumer_credential is unset' do
|
@@ -116,12 +132,17 @@ describe OAuthPolicy do
|
|
116
132
|
|
117
133
|
request = Request.new :get, Addressable::URI.parse('http://xxx/')
|
118
134
|
|
119
|
-
|
135
|
+
expect { OAuthPolicy.authorize request }.to raise_error 'The consumer_credential has not been supplied.'
|
120
136
|
end
|
121
137
|
|
122
138
|
it 'can sign with token' do
|
123
|
-
Clock
|
124
|
-
|
139
|
+
allow(Clock)
|
140
|
+
.to receive(:timestamp)
|
141
|
+
.and_return '1327360530'
|
142
|
+
|
143
|
+
allow(Nonce)
|
144
|
+
.to receive(:next)
|
145
|
+
.and_return '4f610cb28e7aa8711558de5234af1f0e'
|
125
146
|
|
126
147
|
OAuthPolicy.consumer_credential = OAuthCredential.new 'consumer_key', 'consumer_secret'
|
127
148
|
OAuthPolicy.token = OAuthCredential.new 'token_key', 'token_secret'
|
@@ -130,7 +151,7 @@ describe OAuthPolicy do
|
|
130
151
|
|
131
152
|
authorized_request = OAuthPolicy.authorize request
|
132
153
|
|
133
|
-
authorized_request.headers['Authorization'].
|
154
|
+
expect(authorized_request.headers['Authorization']).to match(/oauth_signature="1Boj4fo6KiXA4xGD%2BKF5QOD36PI%3D"/)
|
134
155
|
end
|
135
156
|
|
136
157
|
it 'adds correct signature for https uri'
|