ruby-trello-czuger 2.0.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.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +182 -0
  3. data/lib/trello.rb +163 -0
  4. data/lib/trello/action.rb +68 -0
  5. data/lib/trello/association.rb +14 -0
  6. data/lib/trello/association_proxy.rb +42 -0
  7. data/lib/trello/attachment.rb +40 -0
  8. data/lib/trello/authorization.rb +187 -0
  9. data/lib/trello/basic_data.rb +132 -0
  10. data/lib/trello/board.rb +211 -0
  11. data/lib/trello/card.rb +467 -0
  12. data/lib/trello/checklist.rb +143 -0
  13. data/lib/trello/client.rb +120 -0
  14. data/lib/trello/comment.rb +62 -0
  15. data/lib/trello/configuration.rb +68 -0
  16. data/lib/trello/core_ext/array.rb +6 -0
  17. data/lib/trello/core_ext/hash.rb +6 -0
  18. data/lib/trello/core_ext/string.rb +6 -0
  19. data/lib/trello/cover_image.rb +8 -0
  20. data/lib/trello/has_actions.rb +9 -0
  21. data/lib/trello/item.rb +37 -0
  22. data/lib/trello/item_state.rb +30 -0
  23. data/lib/trello/json_utils.rb +64 -0
  24. data/lib/trello/label.rb +108 -0
  25. data/lib/trello/label_name.rb +31 -0
  26. data/lib/trello/list.rb +114 -0
  27. data/lib/trello/member.rb +112 -0
  28. data/lib/trello/multi_association.rb +12 -0
  29. data/lib/trello/net.rb +39 -0
  30. data/lib/trello/notification.rb +61 -0
  31. data/lib/trello/organization.rb +68 -0
  32. data/lib/trello/plugin_datum.rb +34 -0
  33. data/lib/trello/token.rb +37 -0
  34. data/lib/trello/webhook.rb +103 -0
  35. data/spec/action_spec.rb +149 -0
  36. data/spec/array_spec.rb +13 -0
  37. data/spec/association_spec.rb +26 -0
  38. data/spec/basic_auth_policy_spec.rb +51 -0
  39. data/spec/board_spec.rb +442 -0
  40. data/spec/card_spec.rb +822 -0
  41. data/spec/checklist_spec.rb +296 -0
  42. data/spec/client_spec.rb +257 -0
  43. data/spec/configuration_spec.rb +95 -0
  44. data/spec/hash_spec.rb +15 -0
  45. data/spec/integration/how_to_authorize_spec.rb +53 -0
  46. data/spec/integration/how_to_use_boards_spec.rb +48 -0
  47. data/spec/integration/integration_test.rb +40 -0
  48. data/spec/item_spec.rb +75 -0
  49. data/spec/json_utils_spec.rb +73 -0
  50. data/spec/label_spec.rb +205 -0
  51. data/spec/list_spec.rb +253 -0
  52. data/spec/member_spec.rb +159 -0
  53. data/spec/notification_spec.rb +143 -0
  54. data/spec/oauth_policy_spec.rb +160 -0
  55. data/spec/organization_spec.rb +71 -0
  56. data/spec/spec_helper.rb +435 -0
  57. data/spec/string_spec.rb +55 -0
  58. data/spec/token_spec.rb +89 -0
  59. data/spec/trello_spec.rb +134 -0
  60. data/spec/webhook_spec.rb +130 -0
  61. metadata +200 -0
@@ -0,0 +1,296 @@
1
+ require 'spec_helper'
2
+
3
+ module Trello
4
+ describe Checklist do
5
+ include Helpers
6
+
7
+ let(:checklist) { client.find(:checklist, 'abcdef123456789123456789') }
8
+ let(:client) { Client.new }
9
+
10
+ before do
11
+ allow(client)
12
+ .to receive(:get)
13
+ .with("/checklists/abcdef123456789123456789", {})
14
+ .and_return JSON.generate(checklists_details.first)
15
+ end
16
+
17
+ context "finding" do
18
+ let(:client) { Trello.client }
19
+
20
+ it "delegates to Trello.client#find" do
21
+ expect(client)
22
+ .to receive(:find)
23
+ .with(:checklist, 'abcdef123456789123456789', {})
24
+
25
+ Checklist.find('abcdef123456789123456789')
26
+ end
27
+
28
+ it "is equivalent to client#find" do
29
+ expect(Checklist.find('abcdef123456789123456789')).to eq(checklist)
30
+ end
31
+ end
32
+
33
+ context "creating" do
34
+ let(:client) { Trello.client }
35
+
36
+ it 'creates a new record and saves it on Trello', refactor: true do
37
+ payload = {
38
+ name: 'Test Checklist',
39
+ desc: '',
40
+ card_id: cards_details.first['id']
41
+ }
42
+
43
+ attributes = checklists_details.first.merge(payload).except("idBoard")
44
+ result = JSON.generate(attributes)
45
+
46
+
47
+ expected_payload = {name: "Test Checklist", idCard: cards_details.first['id']}
48
+
49
+ expect(client)
50
+ .to receive(:post)
51
+ .with("/checklists", expected_payload)
52
+ .and_return result
53
+
54
+ checklist = Checklist.create(attributes)
55
+
56
+ expect(checklist).to be_a Checklist
57
+ end
58
+
59
+ it 'initializes all fields from response-like hash' do
60
+ checklist_details = checklists_details.first
61
+ checklist = Checklist.new(checklist_details)
62
+ expect(checklist.id).to eq checklist_details['id']
63
+ expect(checklist.name).to eq checklist_details['name']
64
+ expect(checklist.description).to eq checklist_details['desc']
65
+ expect(checklist.closed).to eq checklist_details['closed']
66
+ expect(checklist.position).to eq checklist_details['pos']
67
+ expect(checklist.url).to eq checklist_details['url']
68
+ expect(checklist.board_id).to eq checklist_details['idBoard']
69
+ expect(checklist.card_id).to eq checklist_details['idCard']
70
+ expect(checklist.list_id).to eq checklist_details['idList']
71
+ expect(checklist.member_ids).to eq checklist_details['idMembers']
72
+ expect(checklist.check_items).to eq checklist_details['checkItems']
73
+ end
74
+
75
+ it 'initializes required fields from options-like hash' do
76
+ checklist_details = checklists_details[1]
77
+ checklist = Checklist.new(checklist_details)
78
+ expect(checklist.name).to eq checklist_details[:name]
79
+ expect(checklist.card_id).to eq checklist_details[:card_id]
80
+ end
81
+ end
82
+
83
+ context "deleting" do
84
+ let(:client) { Trello.client }
85
+
86
+ it "deletes a checklist" do
87
+ expect(client)
88
+ .to receive(:delete)
89
+ .with("/checklists/#{checklist.id}")
90
+
91
+ checklist.delete
92
+ end
93
+
94
+ it "deletes a checklist item" do
95
+ item_id = checklist.check_items.first.last
96
+ expect(client)
97
+ .to receive(:delete)
98
+ .with("/checklists/#{checklist.id}/checkItems/#{item_id}")
99
+
100
+ checklist.delete_checklist_item(item_id)
101
+ end
102
+ end
103
+
104
+ context "updating" do
105
+ it "updating name does a put on the correct resource with the correct value" do
106
+ expected_new_name = "xxx"
107
+ expected_resource = "/checklists/abcdef123456789123456789"
108
+ payload = {
109
+ name: expected_new_name,
110
+ pos: checklist.position
111
+ }
112
+
113
+ result = JSON.generate(checklists_details.first)
114
+ expect(client)
115
+ .to receive(:put)
116
+ .once.with(expected_resource, payload)
117
+ .and_return result
118
+
119
+ checklist.name = expected_new_name
120
+ checklist.save
121
+ end
122
+
123
+ it "updating position does a put on the correct resource with the correct value" do
124
+ expected_new_position = 33
125
+ expected_resource = "/checklists/abcdef123456789123456789"
126
+ payload = {
127
+ name: checklist.name,
128
+ pos: expected_new_position
129
+ }
130
+
131
+ result = JSON.generate(checklists_details.first)
132
+ expect(client)
133
+ .to receive(:put)
134
+ .once
135
+ .with(expected_resource, payload)
136
+ .and_return result
137
+
138
+ checklist.position = expected_new_position
139
+ checklist.save
140
+ end
141
+
142
+ it "adds an item" do
143
+ expected_item_name = "item1"
144
+ expected_checked = true
145
+ expected_pos = 9999
146
+ payload = {
147
+ name: expected_item_name,
148
+ checked: expected_checked,
149
+ pos: expected_pos
150
+ }
151
+ result_hash = {
152
+ name: expected_item_name,
153
+ state: expected_checked ? 'complete' : 'incomplete',
154
+ pos: expected_pos
155
+ }
156
+ result = JSON.generate(result_hash)
157
+ expect(client)
158
+ .to receive(:post)
159
+ .once
160
+ .with("/checklists/abcdef123456789123456789/checkItems", payload)
161
+ .and_return result
162
+
163
+ checklist.add_item(expected_item_name, expected_checked, expected_pos)
164
+ end
165
+
166
+ it "updates an item's state" do
167
+ expected_item_id = "1234"
168
+ expected_state = "incomplete"
169
+ expected_resource =
170
+ "/cards/abccardid/checkItem/#{expected_item_id}"
171
+ payload = { state: expected_state }
172
+ expect(client).to receive(:put).once.with(expected_resource, payload)
173
+ checklist.update_item_state(expected_item_id, expected_state)
174
+ end
175
+
176
+ it "updates an item's with boolean input" do
177
+ expected_item_id = "1234"
178
+ expected_state = "complete"
179
+ expected_resource =
180
+ "/cards/abccardid/checkItem/#{expected_item_id}"
181
+ payload = { state: expected_state }
182
+ expect(client).to receive(:put).once.with(expected_resource, payload)
183
+ checklist.update_item_state(expected_item_id, true)
184
+ end
185
+ end
186
+
187
+ context "board" do
188
+ before do
189
+ allow(client)
190
+ .to receive(:get)
191
+ .with("/boards/abcdef123456789123456789")
192
+ .and_return JSON.generate(boards_details.first)
193
+ end
194
+
195
+ it "has a board" do
196
+ expect(checklist.board).to_not be_nil
197
+ end
198
+ end
199
+
200
+ context "list" do
201
+ before do
202
+ allow(client)
203
+ .to receive(:get)
204
+ .with("/lists/abcdef123456789123456789", {})
205
+ .and_return JSON.generate(lists_details.first)
206
+ end
207
+
208
+ it 'has a list' do
209
+ expect(checklist.list).to_not be_nil
210
+ end
211
+ end
212
+
213
+ context "making a copy" do
214
+ let(:client) { Trello.client }
215
+ let(:copy_options) { { :name => checklist.name, :idCard => checklist.card_id } }
216
+ let(:copied_checklist) { checklist.copy }
217
+
218
+ before(:each) do
219
+ allow(client)
220
+ .to receive(:post)
221
+ .with("/checklists", copy_options)
222
+ .and_return JSON.generate(copied_checklists_details.first)
223
+
224
+ allow(checklist)
225
+ .to receive(:items)
226
+ .and_return []
227
+ end
228
+
229
+ it "creates a new checklist" do
230
+ expect(copied_checklist).to be_an_instance_of Checklist
231
+ end
232
+
233
+ it "is not the same Ruby object as the original checklist" do
234
+ expect(copied_checklist).to_not be checklist
235
+ end
236
+
237
+ it "has the same name as the original checklist" do
238
+ expect(copied_checklist.name).to eq checklist.name
239
+ end
240
+
241
+ it "has the same board as the original checklist" do
242
+ expect(copied_checklist.board_id).to eq checklist.board_id
243
+ end
244
+
245
+ it "creates items for the copy based on the original checklist's items" do
246
+ checklist_copy = Trello::Checklist.new
247
+ allow(checklist_copy)
248
+ .to receive(:add_item)
249
+
250
+ allow(Trello::Checklist)
251
+ .to receive(:create)
252
+ .and_return(checklist_copy)
253
+
254
+ incomplete_item = double("incomplete", name: "1", complete?: false)
255
+ complete_item = double("complete", name: "2", complete?: true)
256
+ checklist_items = [incomplete_item, complete_item]
257
+ allow(checklist).to receive(:items).and_return checklist_items
258
+
259
+ checklist_items.each do |item|
260
+ expect(checklist_copy)
261
+ .to receive(:add_item)
262
+ .with(item.name, item.complete?)
263
+ end
264
+
265
+ checklist.copy
266
+ end
267
+ end
268
+
269
+ describe "#update_fields" do
270
+ it "does not set any fields when the fields argument is empty" do
271
+ expected = {
272
+ 'id' => 'id',
273
+ 'name' => 'name',
274
+ 'desc' => 'description',
275
+ 'closed' => 'closed',
276
+ 'url' => 'url',
277
+ 'checkItems' => 'check_items',
278
+ 'pos' => 'position',
279
+ 'idBoard' => 'board_id',
280
+ 'idCard' => 'card_id',
281
+ 'idList' => 'list_id',
282
+ 'idMembers' => 'member_ids'
283
+ }
284
+
285
+ checklist = Checklist.new(expected)
286
+ checklist.client = client
287
+
288
+ checklist.update_fields({})
289
+
290
+ expected.each do |key, value|
291
+ expect(checklist.send(value)).to eq expected[key]
292
+ end
293
+ end
294
+ end
295
+ end
296
+ end
@@ -0,0 +1,257 @@
1
+ require "spec_helper"
2
+
3
+ include Trello
4
+ include Trello::Authorization
5
+
6
+ describe Client do
7
+
8
+ let(:client) { Client.new }
9
+ let(:auth_policy) { double }
10
+
11
+ before do
12
+ allow(Authorization::AuthPolicy)
13
+ .to receive(:new)
14
+ .and_return(auth_policy)
15
+
16
+ allow(auth_policy)
17
+ .to receive(:authorize) { |request| request }
18
+ end
19
+
20
+ describe "and how it handles RestClient exceptions" do
21
+ context "with RestClient::Exception sans HTTP code" do
22
+ let(:rc_exception_without_http_code) { RestClient::Exception.new }
23
+
24
+ before do
25
+ allow(TInternet)
26
+ .to receive(:execute_core)
27
+ .and_raise(rc_exception_without_http_code)
28
+ end
29
+
30
+ it "bubbles up RestClient::Exception errors that don't contain an HTTP code" do
31
+ expect { client.get "/xxx" }.to raise_error rc_exception_without_http_code
32
+ end
33
+ end
34
+
35
+ context "with RestClient::Exception that contains HTTP code" do
36
+ let(:response_with_non_200_status) { double "A fake 404 response",
37
+ code: 404,
38
+ body: "404 error response"}
39
+ let(:rc_exception_with_http_code) { RestClient::Exception.new(double("404 error response", {:code => 404, :body => "404 error response"}))}
40
+
41
+ before do
42
+ allow(TInternet)
43
+ .to receive(:execute_core)
44
+ .and_raise(rc_exception_with_http_code)
45
+ end
46
+
47
+ it "raises Error" do
48
+
49
+ expect(TInternet)
50
+ .to receive(:try_execute)
51
+ .and_return(response_with_non_200_status)
52
+
53
+ expect { client.get "/xxx" }.to raise_error(Error, "404 error response")
54
+ end
55
+ end
56
+ end
57
+
58
+ describe "and how it handles authorization" do
59
+ let (:fake_ok_response) do
60
+ double "A fake OK response",
61
+ code: 200,
62
+ body: "A fake response body"
63
+ end
64
+ let(:client) { Client.new }
65
+ let(:auth_policy) { double }
66
+
67
+ before do
68
+ allow(TInternet)
69
+ .to receive(:execute)
70
+ .and_return fake_ok_response
71
+
72
+ allow(Authorization::AuthPolicy)
73
+ .to receive(:new)
74
+ .and_return(auth_policy)
75
+
76
+ allow(auth_policy)
77
+ .to receive(:authorize) { |request| request }
78
+ end
79
+
80
+ it "authorizes before it queries the internet" do
81
+ expect(auth_policy)
82
+ .to receive(:authorize)
83
+ .once
84
+ .ordered
85
+
86
+ expect(TInternet)
87
+ .to receive(:execute)
88
+ .once
89
+ .ordered
90
+
91
+ client.get "/xxx"
92
+ end
93
+
94
+ it "queries the internet with expanded earl and query parameters" do
95
+ expected_uri = Addressable::URI.parse("https://api.trello.com/1/xxx?a=1&b=2")
96
+ expected_request = Request.new :get, expected_uri, {}
97
+
98
+ expect(TInternet)
99
+ .to receive(:execute)
100
+ .once
101
+ .with expected_request
102
+
103
+ client.get "/xxx", a: "1", b: "2"
104
+ end
105
+
106
+ it "encodes parameters" do
107
+ expected_uri = Addressable::URI.parse("https://api.trello.com/1/xxx?name=Jazz%20Kang")
108
+ expected_request = Request.new :get, expected_uri, {}
109
+
110
+ expect(TInternet)
111
+ .to receive(:execute)
112
+ .once
113
+ .with expected_request
114
+
115
+ client.get "/xxx", name: "Jazz Kang"
116
+ end
117
+
118
+ it "raises an error when response has non-200 status" do
119
+ expected_error_message = "An error response"
120
+ response_with_non_200_status = double "A fake OK response",
121
+ code: 404,
122
+ body: expected_error_message
123
+
124
+ expect(TInternet)
125
+ .to receive(:execute)
126
+ .and_return response_with_non_200_status
127
+
128
+ expect { client.get "/xxx" }.to raise_error expected_error_message
129
+ end
130
+
131
+ it "uses version 1 of the API" do
132
+ expect(TInternet)
133
+ .to receive(:execute)
134
+ .once do |request|
135
+ expect(request.uri.to_s).to match(/1\//)
136
+ fake_ok_response
137
+ end
138
+
139
+ client.get "/"
140
+ end
141
+
142
+ it "omits the \"?\" when no parameters" do
143
+ expect(TInternet)
144
+ .to receive(:execute)
145
+ .once do |request|
146
+ expect(request.uri.to_s).not_to match(/\?$/)
147
+ fake_ok_response
148
+ end
149
+
150
+ client.get "/xxx"
151
+ end
152
+
153
+ it "supports post" do
154
+ expect(TInternet)
155
+ .to receive(:execute)
156
+ .once
157
+ .and_return fake_ok_response
158
+
159
+ client.post "/xxx", { phil: "T' north" }
160
+ end
161
+
162
+ it "supplies the body for a post" do
163
+ expected_body = { name: "Phil", nickname: "The Crack Fox" }
164
+
165
+ expect(TInternet)
166
+ .to receive(:execute)
167
+ .once do |request|
168
+ expect(request.body).to eq expected_body
169
+ fake_ok_response
170
+ end
171
+
172
+ client.post "/xxx", expected_body
173
+ end
174
+
175
+ it "supplies the path for a post" do
176
+ expected_path = "/xxx"
177
+
178
+ expect(TInternet)
179
+ .to receive(:execute)
180
+ .once do |request|
181
+ expect(request.uri.path).to match(/#{expected_path}$/)
182
+ fake_ok_response
183
+ end
184
+
185
+ client.post "/xxx", {}
186
+ end
187
+
188
+ it "supports put" do
189
+ expect(TInternet)
190
+ .to receive(:execute)
191
+ .once
192
+ .and_return fake_ok_response
193
+
194
+ client.put "/xxx", { phil: "T' north" }
195
+ end
196
+
197
+ it "supplies the body for a put" do
198
+ expected_body = { name: "Phil", nickname: "The Crack Fox" }
199
+
200
+ expect(TInternet)
201
+ .to receive(:execute)
202
+ .once do |request|
203
+ expect(request.body).to eq expected_body
204
+ fake_ok_response
205
+ end
206
+
207
+ client.put "/xxx", expected_body
208
+ end
209
+
210
+ it "supplies the path for a put" do
211
+ expected_path = "/xxx"
212
+
213
+ expect(TInternet)
214
+ .to receive(:execute)
215
+ .once do |request|
216
+ expect(request.uri.path).to match(/#{expected_path}$/)
217
+ fake_ok_response
218
+ end
219
+
220
+ client.put "/xxx", {}
221
+ end
222
+
223
+ context "initialize" do
224
+ let(:client) do
225
+ Client.new(
226
+ consumer_key: 'consumer_key',
227
+ consumer_secret: 'consumer_secret',
228
+ oauth_token: 'oauth_token',
229
+ oauth_token_secret: 'oauth_token_secret'
230
+ )
231
+ end
232
+
233
+ it "is configurable" do
234
+ expect(client.consumer_key).to eq('consumer_key')
235
+ expect(client.consumer_secret).to eq('consumer_secret')
236
+ expect(client.oauth_token).to eq('oauth_token')
237
+ expect(client.oauth_token_secret).to eq('oauth_token_secret')
238
+ end
239
+ end
240
+
241
+ describe "configure" do
242
+ it "sets key attributes through config block" do
243
+ client.configure do |config|
244
+ config.consumer_key = 'consumer_key'
245
+ config.consumer_secret = 'consumer_secret'
246
+ config.oauth_token = 'oauth_token'
247
+ config.oauth_token_secret = 'oauth_token_secret'
248
+ end
249
+
250
+ expect(client.consumer_key).to eq('consumer_key')
251
+ expect(client.consumer_secret).to eq('consumer_secret')
252
+ expect(client.oauth_token).to eq('oauth_token')
253
+ expect(client.oauth_token_secret).to eq('oauth_token_secret')
254
+ end
255
+ end
256
+ end
257
+ end