ruby-trello-wgibbs 0.4.3
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 +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,56 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
include Trello::Authorization
|
4
|
+
|
5
|
+
describe BasicAuthPolicy do
|
6
|
+
before do
|
7
|
+
BasicAuthPolicy.developer_public_key = "xxx"
|
8
|
+
BasicAuthPolicy.member_token = "xxx"
|
9
|
+
end
|
10
|
+
|
11
|
+
it "adds key and token query parameters" do
|
12
|
+
BasicAuthPolicy.developer_public_key = "xxx_developer_public_key_xxx"
|
13
|
+
BasicAuthPolicy.member_token = "xxx_member_token_xxx"
|
14
|
+
|
15
|
+
uri = Addressable::URI.parse("https://xxx/")
|
16
|
+
|
17
|
+
request = Request.new :get, uri
|
18
|
+
|
19
|
+
authorized_request = BasicAuthPolicy.authorize request
|
20
|
+
|
21
|
+
the_query_parameters = Addressable::URI.parse(authorized_request.uri).query_values
|
22
|
+
|
23
|
+
the_query_parameters["key"].should === "xxx_developer_public_key_xxx"
|
24
|
+
the_query_parameters["token"].should === "xxx_member_token_xxx"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "preserves other query parameters" do
|
28
|
+
uri = Addressable::URI.parse("https://xxx/?name=Phil")
|
29
|
+
|
30
|
+
request = Request.new :get, uri, {:example_header => "example_value"}
|
31
|
+
|
32
|
+
authorized_request = BasicAuthPolicy.authorize request
|
33
|
+
|
34
|
+
the_query_parameters = Addressable::URI.parse(authorized_request.uri).query_values
|
35
|
+
|
36
|
+
the_query_parameters["name"].should == "Phil"
|
37
|
+
end
|
38
|
+
|
39
|
+
it "preserves headers" do
|
40
|
+
uri = Addressable::URI.parse("https://xxx/")
|
41
|
+
|
42
|
+
request = Request.new :get, uri, {:example_header => "example_value"}
|
43
|
+
|
44
|
+
authorized_request = BasicAuthPolicy.authorize request
|
45
|
+
|
46
|
+
authorized_request.headers.should === request.headers
|
47
|
+
end
|
48
|
+
|
49
|
+
it "returns nil body if one is supplied" do
|
50
|
+
uri = Addressable::URI.parse("https://xxx/")
|
51
|
+
request = Request.new :get, uri, {}, "any body"
|
52
|
+
BasicAuthPolicy.authorize(request).body.should be_nil
|
53
|
+
end
|
54
|
+
|
55
|
+
it "does what when a query parameter already exists called key or token?"
|
56
|
+
end
|
data/spec/board_spec.rb
ADDED
@@ -0,0 +1,196 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Trello
|
4
|
+
describe Board do
|
5
|
+
include Helpers
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
Client.stub(:get).with("/boards/abcdef123456789123456789").
|
9
|
+
and_return JSON.generate(boards_details.first)
|
10
|
+
|
11
|
+
@board = Board.find('abcdef123456789123456789')
|
12
|
+
end
|
13
|
+
|
14
|
+
context "fields" do
|
15
|
+
it "gets an id" do
|
16
|
+
@board.id.should_not be_nil
|
17
|
+
end
|
18
|
+
|
19
|
+
it "gets a name" do
|
20
|
+
@board.name.should_not be_nil
|
21
|
+
end
|
22
|
+
|
23
|
+
it "gets the description" do
|
24
|
+
@board.description.should_not be_nil
|
25
|
+
end
|
26
|
+
|
27
|
+
it "knows if it is closed or open" do
|
28
|
+
@board.closed?.should_not be_nil
|
29
|
+
end
|
30
|
+
|
31
|
+
it "gets its url" do
|
32
|
+
@board.url.should_not be_nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "actions" do
|
37
|
+
it "has a list of actions" do
|
38
|
+
Client.stub(:get).with("/boards/abcdef123456789123456789/actions", {:filter => :all}).
|
39
|
+
and_return actions_payload
|
40
|
+
|
41
|
+
@board.actions.count.should be > 0
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "cards" do
|
46
|
+
it "gets its list of cards" do
|
47
|
+
Client.stub(:get).with("/boards/abcdef123456789123456789/cards", { :filter => :open }).
|
48
|
+
and_return cards_payload
|
49
|
+
|
50
|
+
@board.cards.count.should be > 0
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "lists" do
|
55
|
+
it "has a list of lists" do
|
56
|
+
Client.stub(:get).with("/boards/abcdef123456789123456789/lists", hash_including(:filter => :open)).
|
57
|
+
and_return lists_payload
|
58
|
+
|
59
|
+
@board.has_lists?.should be true
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "members" do
|
64
|
+
it "has a list of members" do
|
65
|
+
Client.stub(:get).with("/boards/abcdef123456789123456789/members", hash_including(:filter => :all)).
|
66
|
+
and_return JSON.generate([user_details])
|
67
|
+
|
68
|
+
@board.members.count.should be > 0
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "organization" do
|
73
|
+
it "belongs to an organization" do
|
74
|
+
Client.stub(:get).with("/organizations/abcdef123456789123456789").
|
75
|
+
and_return JSON.generate(orgs_details.first)
|
76
|
+
|
77
|
+
@board.organization.should_not be_nil
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it "is not closed" do
|
82
|
+
@board.closed?.should_not be_true
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "#update_fields" do
|
87
|
+
it "does not set any fields when the fields argument is empty" do
|
88
|
+
expected = {
|
89
|
+
'id' => "id",
|
90
|
+
'name' => "name",
|
91
|
+
'desc' => "desc",
|
92
|
+
'closed' => false,
|
93
|
+
'url' => "url",
|
94
|
+
'idOrganization' => "org_id"
|
95
|
+
}
|
96
|
+
|
97
|
+
board = Board.new(expected)
|
98
|
+
|
99
|
+
board.update_fields({})
|
100
|
+
|
101
|
+
expected.each_pair do |key, value|
|
102
|
+
if board.respond_to?(key)
|
103
|
+
board.send(key).should == value
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
board.description.should == expected['desc']
|
108
|
+
board.organization_id.should == expected['idOrganization']
|
109
|
+
end
|
110
|
+
|
111
|
+
it "sets any attributes supplied in the fields argument"
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "#save" do
|
115
|
+
include Helpers
|
116
|
+
|
117
|
+
let(:any_board_json) do
|
118
|
+
JSON.generate(boards_details.first)
|
119
|
+
end
|
120
|
+
|
121
|
+
it "cannot currently save a new instance" do
|
122
|
+
Client.should_not_receive :put
|
123
|
+
|
124
|
+
the_new_board = Board.new
|
125
|
+
lambda{the_new_board.save}.should raise_error
|
126
|
+
end
|
127
|
+
|
128
|
+
it "puts all fields except id" do
|
129
|
+
expected_fields = %w{name description closed}.map{|s| s.to_sym}
|
130
|
+
|
131
|
+
Client.should_receive(:put) do |anything, body|
|
132
|
+
body.keys.should =~ expected_fields
|
133
|
+
any_board_json
|
134
|
+
end
|
135
|
+
|
136
|
+
the_new_board = Board.new 'id' => "xxx"
|
137
|
+
the_new_board.save
|
138
|
+
end
|
139
|
+
|
140
|
+
it "mutates the current instance" do
|
141
|
+
Client.stub(:put).and_return any_board_json
|
142
|
+
|
143
|
+
board = Board.new 'id' => "xxx"
|
144
|
+
|
145
|
+
the_result_of_save = board.save
|
146
|
+
|
147
|
+
the_result_of_save.should equal board
|
148
|
+
end
|
149
|
+
|
150
|
+
it "uses the correct resource" do
|
151
|
+
expected_resource_id = "xxx_board_id_xxx"
|
152
|
+
|
153
|
+
Client.should_receive(:put) do |path, anything|
|
154
|
+
path.should =~ /#{expected_resource_id}\/$/
|
155
|
+
any_board_json
|
156
|
+
end
|
157
|
+
|
158
|
+
the_new_board = Board.new 'id' => expected_resource_id
|
159
|
+
the_new_board.save
|
160
|
+
end
|
161
|
+
|
162
|
+
it "saves OR updates depending on whether or not it has an id set"
|
163
|
+
end
|
164
|
+
|
165
|
+
describe "Repository" do
|
166
|
+
include Helpers
|
167
|
+
|
168
|
+
let(:any_board_json) do
|
169
|
+
JSON.generate(boards_details.first)
|
170
|
+
end
|
171
|
+
|
172
|
+
it "creates a new board with whatever attributes are supplied " do
|
173
|
+
expected_attributes = { :name => "Any new board name", :description => "Any new board desription" }
|
174
|
+
sent_attributes = { :name => expected_attributes[:name], :desc => expected_attributes[:description] }
|
175
|
+
|
176
|
+
Client.should_receive(:post).with("/boards", sent_attributes).and_return any_board_json
|
177
|
+
|
178
|
+
Board.create expected_attributes
|
179
|
+
end
|
180
|
+
|
181
|
+
it "posts to the boards collection" do
|
182
|
+
Client.should_receive(:post).with("/boards", anything).and_return any_board_json
|
183
|
+
|
184
|
+
Board.create :xxx => ""
|
185
|
+
end
|
186
|
+
|
187
|
+
it "returns a board" do
|
188
|
+
Client.stub(:post).with("/boards", anything).and_return any_board_json
|
189
|
+
|
190
|
+
the_new_board = Board.create :xxx => ""
|
191
|
+
the_new_board.should be_a Board
|
192
|
+
end
|
193
|
+
|
194
|
+
it "at least name is required"
|
195
|
+
end
|
196
|
+
end
|
data/spec/card_spec.rb
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Trello
|
4
|
+
describe Card do
|
5
|
+
include Helpers
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
Client.stub(:get).with("/cards/abcdef123456789123456789").
|
9
|
+
and_return JSON.generate(cards_details.first)
|
10
|
+
|
11
|
+
@card = Card.find('abcdef123456789123456789')
|
12
|
+
end
|
13
|
+
|
14
|
+
context "creating" do
|
15
|
+
it "creates a new record" do
|
16
|
+
card = Card.new(cards_details.first)
|
17
|
+
card.should be_valid
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'must not be valid if not given a name' do
|
21
|
+
card = Card.new('idList' => lists_details.first['id'])
|
22
|
+
card.should_not be_valid
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'must not be valid if not given a list id' do
|
26
|
+
card = Card.new('name' => lists_details.first['name'])
|
27
|
+
card.should_not be_valid
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'creates a new record and saves it on Trello', :refactor => true do
|
31
|
+
payload = {
|
32
|
+
:name => 'Test Card',
|
33
|
+
:desc => '',
|
34
|
+
}
|
35
|
+
|
36
|
+
result = JSON.generate(cards_details.first.merge(payload.merge(:idList => lists_details.first['id'])))
|
37
|
+
|
38
|
+
expected_payload = {:name => "Test Card", :desc => nil, :idList => "abcdef123456789123456789"}
|
39
|
+
|
40
|
+
Client.should_receive(:post).with("/cards", expected_payload).and_return result
|
41
|
+
|
42
|
+
card = Card.create(cards_details.first.merge(payload.merge(:list_id => lists_details.first['id'])))
|
43
|
+
|
44
|
+
card.class.should be Card
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "updating" do
|
49
|
+
it "updating name does a put on the correct resource with the correct value" do
|
50
|
+
expected_new_name = "xxx"
|
51
|
+
expected_resource = "/card/#{@card.id}/name"
|
52
|
+
payload = {
|
53
|
+
:name => expected_new_name,
|
54
|
+
:desc => "Awesome things are awesome.",
|
55
|
+
:due => nil,
|
56
|
+
:closed => false,
|
57
|
+
:idList => "abcdef123456789123456789",
|
58
|
+
:idBoard => "abcdef123456789123456789",
|
59
|
+
:idMembers => ["abcdef123456789123456789"]
|
60
|
+
}
|
61
|
+
|
62
|
+
Client.should_receive(:put).once.with("/cards/abcdef123456789123456789", payload)
|
63
|
+
card = @card.dup
|
64
|
+
card.name = expected_new_name
|
65
|
+
card.save
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "fields" do
|
70
|
+
it "gets its id" do
|
71
|
+
@card.id.should_not be_nil
|
72
|
+
end
|
73
|
+
|
74
|
+
it "gets its short id" do
|
75
|
+
@card.short_id.should_not be_nil
|
76
|
+
end
|
77
|
+
|
78
|
+
it "gets its name" do
|
79
|
+
@card.name.should_not be_nil
|
80
|
+
end
|
81
|
+
|
82
|
+
it "gets its description" do
|
83
|
+
@card.description.should_not be_nil
|
84
|
+
end
|
85
|
+
|
86
|
+
it "knows if it is open or closed" do
|
87
|
+
@card.closed.should_not be_nil
|
88
|
+
end
|
89
|
+
|
90
|
+
it "gets its url" do
|
91
|
+
@card.url.should_not be_nil
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context "actions" do
|
96
|
+
it "asks for all actions by default" do
|
97
|
+
Client.stub(:get).with("/cards/abcdef123456789123456789/actions", { :filter => :all }).and_return actions_payload
|
98
|
+
@card.actions.count.should be > 0
|
99
|
+
end
|
100
|
+
|
101
|
+
it "allows overriding the filter" do
|
102
|
+
Client.stub(:get).with("/cards/abcdef123456789123456789/actions", { :filter => :updateCard }).and_return actions_payload
|
103
|
+
@card.actions(:filter => :updateCard).count.should be > 0
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context "boards" do
|
108
|
+
it "has a board" do
|
109
|
+
Client.stub(:get).with("/boards/abcdef123456789123456789").and_return JSON.generate(boards_details.first)
|
110
|
+
@card.board.should_not be_nil
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context "checklists" do
|
115
|
+
it "has a list of checklists" do
|
116
|
+
Client.stub(:get).with("/cards/abcdef123456789123456789/checklists", { :filter => :all }).and_return checklists_payload
|
117
|
+
@card.checklists.count.should be > 0
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context "list" do
|
122
|
+
it 'has a list' do
|
123
|
+
Client.stub(:get).with("/lists/abcdef123456789123456789").and_return JSON.generate(lists_details.first)
|
124
|
+
@card.list.should_not be_nil
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'can be moved to another list' do
|
128
|
+
other_list = stub(:id => '987654321987654321fedcba')
|
129
|
+
payload = {:value => other_list.id}
|
130
|
+
Client.should_receive(:put).with("/cards/abcdef123456789123456789/idList", payload)
|
131
|
+
@card.move_to_list(other_list)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context "members" do
|
136
|
+
it "has a list of members" do
|
137
|
+
Client.stub(:get).with("/boards/abcdef123456789123456789").and_return JSON.generate(boards_details.first)
|
138
|
+
Client.stub(:get).with("/members/abcdef123456789123456789").and_return user_payload
|
139
|
+
|
140
|
+
@card.board.should_not be_nil
|
141
|
+
@card.members.should_not be_nil
|
142
|
+
end
|
143
|
+
|
144
|
+
it "allows a member to be added to a card" do
|
145
|
+
new_member = stub(:id => '4ee7df3ce582acdec80000b2')
|
146
|
+
payload = {
|
147
|
+
:value => new_member.id
|
148
|
+
}
|
149
|
+
Client.should_receive(:post).with("/cards/abcdef123456789123456789/members", payload)
|
150
|
+
@card.add_member(new_member)
|
151
|
+
end
|
152
|
+
|
153
|
+
it "allows a member to be removed from a card" do
|
154
|
+
existing_member = stub(:id => '4ee7df3ce582acdec80000b2')
|
155
|
+
Client.should_receive(:delete).with("/cards/abcdef123456789123456789/members/#{existing_member.id}")
|
156
|
+
@card.remove_member(existing_member)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context "comments" do
|
161
|
+
it "posts a comment" do
|
162
|
+
Client.should_receive(:post).
|
163
|
+
with("/cards/abcdef123456789123456789/actions/comments", { :text => 'testing' }).
|
164
|
+
and_return JSON.generate(boards_details.first)
|
165
|
+
|
166
|
+
@card.add_comment "testing"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context "labels" do
|
171
|
+
it "can retrieve labels" do
|
172
|
+
Client.stub(:get).with("/cards/abcdef123456789123456789/labels").
|
173
|
+
and_return label_payload
|
174
|
+
labels = @card.labels
|
175
|
+
labels.size.should == 2
|
176
|
+
|
177
|
+
labels[0].color.should == 'yellow'
|
178
|
+
labels[0].name.should == 'iOS'
|
179
|
+
|
180
|
+
labels[1].color.should == 'purple'
|
181
|
+
labels[1].name.should == 'Issue or bug'
|
182
|
+
end
|
183
|
+
|
184
|
+
it "can add a label" do
|
185
|
+
Client.stub(:post).with("/cards/abcdef123456789123456789/labels", { :value => 'green' }).
|
186
|
+
and_return "not important"
|
187
|
+
@card.add_label('green')
|
188
|
+
@card.errors.should be_empty
|
189
|
+
end
|
190
|
+
|
191
|
+
it "can remove a label" do
|
192
|
+
Client.stub(:delete).with("/cards/abcdef123456789123456789/labels/green").
|
193
|
+
and_return "not important"
|
194
|
+
@card.remove_label('green')
|
195
|
+
@card.errors.should be_empty
|
196
|
+
end
|
197
|
+
|
198
|
+
it "throws an error when trying to add a label with an unknown colour" do
|
199
|
+
Client.stub(:post).with("/cards/abcdef123456789123456789/labels", { :value => 'green' }).
|
200
|
+
and_return "not important"
|
201
|
+
@card.add_label('mauve')
|
202
|
+
@card.errors.full_messages.to_sentence.should == "Label colour 'mauve' does not exist"
|
203
|
+
end
|
204
|
+
|
205
|
+
it "throws an error when trying to remove a label with an unknown colour" do
|
206
|
+
Client.stub(:delete).with("/cards/abcdef123456789123456789/labels/mauve").
|
207
|
+
and_return "not important"
|
208
|
+
@card.remove_label('mauve')
|
209
|
+
@card.errors.full_messages.to_sentence.should == "Label colour 'mauve' does not exist"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Trello
|
4
|
+
describe Checklist do
|
5
|
+
include Helpers
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
Client.stub(:get).with("/checklists/abcdef123456789123456789").
|
9
|
+
and_return JSON.generate(checklists_details.first)
|
10
|
+
|
11
|
+
@checklist = Checklist.find('abcdef123456789123456789')
|
12
|
+
end
|
13
|
+
|
14
|
+
context "creating" do
|
15
|
+
it 'creates a new record and saves it on Trello', :refactor => true do
|
16
|
+
payload = {
|
17
|
+
:name => 'Test Checklist',
|
18
|
+
:desc => '',
|
19
|
+
}
|
20
|
+
|
21
|
+
result = JSON.generate(checklists_details.first.merge(payload.merge(:idBoard => boards_details.first['id'])))
|
22
|
+
|
23
|
+
expected_payload = {:name => "Test Checklist", :idBoard => "abcdef123456789123456789"}
|
24
|
+
|
25
|
+
Client.should_receive(:post).with("/checklists", expected_payload).and_return result
|
26
|
+
|
27
|
+
checklist = Checklist.create(checklists_details.first.merge(payload.merge(:board_id => boards_details.first['id'])))
|
28
|
+
|
29
|
+
checklist.class.should be Checklist
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "updating" do
|
34
|
+
it "updating name does a put on the correct resource with the correct value" do
|
35
|
+
expected_new_name = "xxx"
|
36
|
+
expected_resource = "/checklists/#{@checklist.id}"
|
37
|
+
payload = {
|
38
|
+
:name => expected_new_name
|
39
|
+
}
|
40
|
+
|
41
|
+
result = JSON.generate(checklists_details.first)
|
42
|
+
Client.should_receive(:put).once.with("/checklists/abcdef123456789123456789", payload).and_return result
|
43
|
+
checklist = @checklist.dup
|
44
|
+
checklist.name = expected_new_name
|
45
|
+
checklist.save
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
include Trello
|
4
|
+
include Trello::Authorization
|
5
|
+
|
6
|
+
describe Client, "and how it handles authorization" do
|
7
|
+
let (:fake_ok_response) {
|
8
|
+
stub "A fake OK response",
|
9
|
+
:code => 200,
|
10
|
+
:body => "A fake response body"
|
11
|
+
}
|
12
|
+
|
13
|
+
before do
|
14
|
+
TInternet.stub(:execute).and_return fake_ok_response
|
15
|
+
Authorization::AuthPolicy.stub(:authorize) do |request|
|
16
|
+
request
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it "authorizes before it queries the internet" do
|
21
|
+
AuthPolicy.should_receive(:authorize).once.ordered
|
22
|
+
TInternet.should_receive(:execute).once.ordered
|
23
|
+
|
24
|
+
Client.get "/xxx"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "queries the internet with expanded earl and query parameters" do
|
28
|
+
expected_uri = Addressable::URI.parse("https://api.trello.com/1/xxx?a=1&b=2")
|
29
|
+
expected_request = Request.new :get, expected_uri, {}
|
30
|
+
|
31
|
+
TInternet.should_receive(:execute).once.with expected_request
|
32
|
+
|
33
|
+
Client.get "/xxx", :a => "1", :b => "2"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "encodes parameters" do
|
37
|
+
expected_uri = Addressable::URI.parse("https://api.trello.com/1/xxx?name=Jazz%20Kang")
|
38
|
+
expected_request = Request.new :get, expected_uri, {}
|
39
|
+
|
40
|
+
TInternet.should_receive(:execute).once.with expected_request
|
41
|
+
|
42
|
+
Client.get "/xxx", :name => "Jazz Kang"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "raises an error when response has non-200 status" do
|
46
|
+
expected_error_message = "An error response"
|
47
|
+
response_with_non_200_status = stub "A fake OK response",
|
48
|
+
:code => 404,
|
49
|
+
:body => expected_error_message
|
50
|
+
|
51
|
+
TInternet.stub(:execute).and_return response_with_non_200_status
|
52
|
+
|
53
|
+
lambda{Client.get "/xxx"}.should raise_error expected_error_message
|
54
|
+
end
|
55
|
+
|
56
|
+
it "uses version 1 of the API" do
|
57
|
+
TInternet.should_receive(:execute).once do |request|
|
58
|
+
request.uri.to_s.should =~ /1\//
|
59
|
+
fake_ok_response
|
60
|
+
end
|
61
|
+
|
62
|
+
Client.get "/"
|
63
|
+
end
|
64
|
+
|
65
|
+
it "omits the \"?\" when no parameters" do
|
66
|
+
TInternet.should_receive(:execute).once do |request|
|
67
|
+
request.uri.to_s.should_not =~ /\?$/
|
68
|
+
fake_ok_response
|
69
|
+
end
|
70
|
+
|
71
|
+
Client.get "/xxx"
|
72
|
+
end
|
73
|
+
|
74
|
+
it "supports post" do
|
75
|
+
TInternet.should_receive(:execute).once.and_return fake_ok_response
|
76
|
+
|
77
|
+
Client.post "/xxx", { :phil => "T' north" }
|
78
|
+
end
|
79
|
+
|
80
|
+
it "supplies the body for a post" do
|
81
|
+
expected_body = { :name => "Phil", :nickname => "The Crack Fox" }
|
82
|
+
|
83
|
+
TInternet.should_receive(:execute).once do |request|
|
84
|
+
request.body.should == expected_body
|
85
|
+
fake_ok_response
|
86
|
+
end
|
87
|
+
|
88
|
+
Client.post "/xxx", expected_body
|
89
|
+
end
|
90
|
+
|
91
|
+
it "supplies the path for a post" do
|
92
|
+
expected_path = "/xxx"
|
93
|
+
|
94
|
+
TInternet.should_receive(:execute).once do |request|
|
95
|
+
request.uri.path.should =~ /#{expected_path}$/
|
96
|
+
fake_ok_response
|
97
|
+
end
|
98
|
+
|
99
|
+
Client.post "/xxx", {}
|
100
|
+
end
|
101
|
+
|
102
|
+
it "supports put" do
|
103
|
+
expected_path = "/xxx"
|
104
|
+
|
105
|
+
TInternet.should_receive(:execute).once.and_return fake_ok_response
|
106
|
+
|
107
|
+
Client.put "/xxx", { :phil => "T' north" }
|
108
|
+
end
|
109
|
+
|
110
|
+
it "supplies the body for a put" do
|
111
|
+
expected_body = { :name => "Phil", :nickname => "The Crack Fox" }
|
112
|
+
|
113
|
+
TInternet.should_receive(:execute).once do |request|
|
114
|
+
request.body.should == expected_body
|
115
|
+
fake_ok_response
|
116
|
+
end
|
117
|
+
|
118
|
+
Client.put "/xxx", expected_body
|
119
|
+
end
|
120
|
+
|
121
|
+
it "supplies the path for a put" do
|
122
|
+
expected_path = "/xxx"
|
123
|
+
|
124
|
+
TInternet.should_receive(:execute).once do |request|
|
125
|
+
request.uri.path.should =~ /#{expected_path}$/
|
126
|
+
fake_ok_response
|
127
|
+
end
|
128
|
+
|
129
|
+
Client.put "/xxx", {}
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'integration/integration_test'
|
3
|
+
|
4
|
+
describe "Authorizing read-only requests", :broken => true do
|
5
|
+
include IntegrationTest
|
6
|
+
|
7
|
+
it "Reading public resources requires just a developer public key" do
|
8
|
+
uri = Addressable::URI.parse("https://api.trello.com/1/boards/4ed7e27fe6abb2517a21383d")
|
9
|
+
uri.query_values = {
|
10
|
+
:key => @developer_public_key
|
11
|
+
}
|
12
|
+
|
13
|
+
get(uri).code.should === 200
|
14
|
+
end
|
15
|
+
|
16
|
+
it "Reading private resources requires developer public key AND a member token" do
|
17
|
+
uri = Addressable::URI.parse("https://api.trello.com/1/boards/#{@welcome_board}")
|
18
|
+
uri.query_values = {
|
19
|
+
:key => @developer_public_key,
|
20
|
+
:token => @member_token
|
21
|
+
}
|
22
|
+
|
23
|
+
get(uri).code.should === 200
|
24
|
+
end
|
25
|
+
|
26
|
+
it "can fetch the welcome board" do
|
27
|
+
BasicAuthPolicy.developer_public_key = @developer_public_key
|
28
|
+
BasicAuthPolicy.member_token = @member_token
|
29
|
+
|
30
|
+
Container.set Trello::Authorization, "AuthPolicy", BasicAuthPolicy
|
31
|
+
|
32
|
+
welcome_board = Board.find @welcome_board
|
33
|
+
welcome_board.name.should === "Welcome Board"
|
34
|
+
welcome_board.id.should === @welcome_board
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "OAuth", :broken => true do
|
39
|
+
include IntegrationTest
|
40
|
+
|
41
|
+
before do
|
42
|
+
Container.set Trello::Authorization, "AuthPolicy", OAuthPolicy
|
43
|
+
end
|
44
|
+
|
45
|
+
it "[!] actually does not enforce signature at all, only the keys are required" do
|
46
|
+
OAuthPolicy.consumer_credential = OAuthCredential.new @developer_public_key, nil
|
47
|
+
OAuthPolicy.token = OAuthCredential.new @access_token_key, nil
|
48
|
+
|
49
|
+
pending "I would expect this to fail because I have signed with nil secrets" do
|
50
|
+
lambda{Client.get("/boards/#{@welcome_board}/")}.should raise_error
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|