ruby-trello 1.2.1 → 1.3.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.
- 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'
|