ruby-trello 1.4.2 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: eff2182d04d8c17e2f7978adac83a17b053e77c2
4
- data.tar.gz: 98a0c4853b9033260ee8b7095dddcf2b65899d42
3
+ metadata.gz: 3131b86cac06b4df9efe8f417ab1bd32de3cbdb1
4
+ data.tar.gz: 862affe69703265224606c58b6a72cb5e8c1f668
5
5
  SHA512:
6
- metadata.gz: 8e50b332a4d61974e2c27dd2d2e9d110bb54971d668ea659cca4f06762d0d42b155da98c00e391eb151451983e95405e44545425841692647e9ca17b3bdbe7c0
7
- data.tar.gz: 2b3526b6a11edee0d6ba2357f4fda861bc2c2c0c376f8df945fe4dd412ed2e86589a4be66892765e8de581314fb265172fd0c009e38636f65bde74abceb36fa4
6
+ metadata.gz: 3f6f8f608417641e88c05ab8df2ebdb5e50bff8f522070be335d3be733d9eca5f6cd5470e34de6542875a9d1dfbb4b2dd78147403d035b2c4e931ebfb15c42e1
7
+ data.tar.gz: 1e53a8176105929d6c972888e3d6b218bbba627b92abcef67b6e660119ac5371dbca524c4fd2990751750a267ad318fc67803a95dc083dfc17b743053534c562
data/README.md CHANGED
@@ -20,7 +20,10 @@ Seriously, [check it out](http://www.trello.com/).
20
20
  Full Disclosure: This library is mostly complete, if you do find anything missing or not functioning as you expect it
21
21
  to, please [let us know](https://trello.com/card/spot-a-bug-report-it/4f092b2ee23cb6fe6d1aaabd/17).
22
22
 
23
- Supports Ruby 2.0 or newer. Version 1.3.0 is the last version that supports Ruby that is older than 1.9.3.
23
+ Supports Ruby 2.1.0 or newer.
24
+
25
+ Use version 1.3.0 or earlier for ruby 1.9.3 support.
26
+ Use version 1.4.x or earlier for ruby 2.0.0 support.
24
27
 
25
28
  ## Configuration
26
29
 
@@ -29,6 +29,8 @@ module Trello
29
29
  # @return [Dateime]
30
30
  # @!attribute [rw] card_labels
31
31
  # @return [Array<Hash>]
32
+ # @!attribute [rw] labels
33
+ # @return [Array<Trello::Labels>]
32
34
  # @!attribute [rw] cover_image_id
33
35
  # @return [String] A 24-character hex string
34
36
  # @!attribute [r] badges
@@ -42,7 +44,7 @@ module Trello
42
44
 
43
45
  class Card < BasicData
44
46
  register_attributes :id, :short_id, :name, :desc, :due, :closed, :url, :short_url,
45
- :board_id, :member_ids, :list_id, :pos, :last_activity_date, :card_labels,
47
+ :board_id, :member_ids, :list_id, :pos, :last_activity_date, :labels, :card_labels,
46
48
  :cover_image_id, :badges, :card_members, :source_card_id, :source_card_properties,
47
49
  readonly: [ :id, :short_id, :url, :short_url, :last_activity_date, :badges, :card_members ]
48
50
  validates_presence_of :id, :name, :list_id
@@ -67,6 +69,7 @@ module Trello
67
69
  pos: 'pos',
68
70
  last_activity_date: 'dateLastActivity',
69
71
  card_labels: 'idLabels',
72
+ labels: 'labels',
70
73
  badges: 'badges',
71
74
  card_members: 'members',
72
75
  source_card_id: "idCardSource",
@@ -151,6 +154,8 @@ module Trello
151
154
  # (24-character hex strings).
152
155
  # @option fields [String] :pos A position. `"top"`, `"bottom"`, or a
153
156
  # positive number. Defaults to `"bottom"`.
157
+ # @option fields [Array] :labels An Array of Trello::Label objects
158
+ # derived from the JSON response
154
159
  # @option fields [String] :card_labels A comma-separated list of
155
160
  # objectIds (24-character hex strings).
156
161
  # @option fields [Object] :cover_image_id
@@ -173,6 +178,7 @@ module Trello
173
178
  attributes[:member_ids] = fields[SYMBOL_TO_STRING[:member_ids]]
174
179
  attributes[:list_id] = fields[SYMBOL_TO_STRING[:list_id]]
175
180
  attributes[:pos] = fields[SYMBOL_TO_STRING[:pos]]
181
+ attributes[:labels] = (fields[SYMBOL_TO_STRING[:labels]] || []).map { |lbl| Trello::Label.new(lbl) }
176
182
  attributes[:card_labels] = fields[SYMBOL_TO_STRING[:card_labels]]
177
183
  attributes[:last_activity_date] = Time.iso8601(fields[SYMBOL_TO_STRING[:last_activity_date]]) rescue nil
178
184
  attributes[:cover_image_id] = fields[SYMBOL_TO_STRING[:cover_image_id]]
@@ -200,8 +206,6 @@ module Trello
200
206
  MultiAssociation.new(self, states).proxy
201
207
  end
202
208
 
203
- many :labels
204
-
205
209
  # Returns a reference to the list this card is currently in.
206
210
  one :list, path: :lists, using: :list_id
207
211
 
@@ -215,6 +219,16 @@ module Trello
215
219
  MultiAssociation.new(self, members).proxy
216
220
  end
217
221
 
222
+ # Returns a list of members who have upvoted this card
223
+ # NOTE: this fetches a list each time it's called to avoid case where
224
+ # card is voted (or vote is removed) after card is fetched. Optimizing
225
+ # accuracy over network performance
226
+ #
227
+ # @return [Array<Trello::Member>]
228
+ def voters
229
+ Member.from_response client.get("/cards/#{id}/membersVoted")
230
+ end
231
+
218
232
  # Saves a record.
219
233
  #
220
234
  # @raise [Trello::Error] if the card could not be saved
@@ -340,6 +354,30 @@ module Trello
340
354
  client.delete("/cards/#{id}/members/#{member.id}")
341
355
  end
342
356
 
357
+ # Current authenticated user upvotes a card
358
+ def upvote
359
+ begin
360
+ client.post("/cards/#{id}/membersVoted", {
361
+ value: me.id
362
+ })
363
+ rescue Trello::Error => e
364
+ fail e unless e.message =~ /has already voted/i
365
+ end
366
+
367
+ self
368
+ end
369
+
370
+ # Recind upvote. Noop if authenticated user hasn't previously voted
371
+ def remove_upvote
372
+ begin
373
+ client.delete("/cards/#{id}/membersVoted/#{me.id}")
374
+ rescue Trello::Error => e
375
+ fail e unless e.message =~ /has not voted/i
376
+ end
377
+
378
+ self
379
+ end
380
+
343
381
  # Add a label
344
382
  def add_label(label)
345
383
  unless label.valid?
@@ -360,7 +398,8 @@ module Trello
360
398
 
361
399
  # Add an attachment to this card
362
400
  def add_attachment(attachment, name='')
363
- if attachment.is_a? File
401
+ # Is it a file object or a string (url)?
402
+ if attachment.respond_to?(:path) && attachment.respond_to?(:read)
364
403
  client.post("/cards/#{id}/attachments", {
365
404
  file: attachment,
366
405
  name: name
@@ -393,5 +432,16 @@ module Trello
393
432
  def comments
394
433
  comments = Comment.from_response client.get("/cards/#{id}/actions", filter: "commentCard")
395
434
  end
435
+
436
+ # Find the creation date
437
+ def created_at
438
+ @created_at ||= Time.at(id[0..7].to_i(16)) rescue nil
439
+ end
440
+
441
+ private
442
+
443
+ def me
444
+ @me ||= Member.find(:me)
445
+ end
396
446
  end
397
447
  end
@@ -107,6 +107,14 @@ module Trello
107
107
  client.post("/checklists/#{id}/checkItems", {name: name, checked: checked, pos: position})
108
108
  end
109
109
 
110
+ # Update a checklist item's state, e.g.: "complete" or "incomplete"
111
+ def update_item_state(item_id, state)
112
+ client.put(
113
+ "/cards/#{card_id}/checklist/#{id}/checkItem/#{item_id}/state",
114
+ value: state,
115
+ )
116
+ end
117
+
110
118
  # Delete a checklist item
111
119
  def delete_checklist_item(item_id)
112
120
  client.delete("/checklists/#{id}/checkItems/#{item_id}")
@@ -119,7 +127,7 @@ module Trello
119
127
 
120
128
  # Copy a checklist (i.e., same attributes, items, etc.)
121
129
  def copy
122
- checklist_copy = self.class.create(name: self.name, board_id: self.board_id)
130
+ checklist_copy = self.class.create(name: self.name, board_id: self.board_id, card_id: self.card_id)
123
131
  copy_items_to(checklist_copy)
124
132
  return checklist_copy
125
133
  end
@@ -20,11 +20,13 @@ module Trello
20
20
  # Supply a hash of string keyed data retrieved from the Trello API representing
21
21
  # an item.
22
22
  def update_fields(fields)
23
- attributes[:id] = fields['id']
24
- attributes[:name] = fields['name']
25
- attributes[:type] = fields['type']
26
- attributes[:state] = fields['state']
27
- attributes[:pos] = fields['pos']
23
+ attributes[:id] = fields['id']
24
+ attributes[:card_id] = fields['idCard']
25
+ attributes[:checklist_id] = fields['idChecklist']
26
+ attributes[:name] = fields['name']
27
+ attributes[:type] = fields['type']
28
+ attributes[:state] = fields['state']
29
+ attributes[:pos] = fields['pos']
28
30
  self
29
31
  end
30
32
 
@@ -12,7 +12,7 @@ module Trello
12
12
  # @!attribute [rw] pos
13
13
  # @return [Object]
14
14
  class List < BasicData
15
- register_attributes :id, :name, :closed, :board_id, :pos, readonly: [ :id, :board_id ]
15
+ register_attributes :id, :name, :closed, :board_id, :pos, :source_list_id, readonly: [ :id, :board_id ]
16
16
  validates_presence_of :id, :name, :board_id
17
17
  validates_length_of :name, in: 1..16384
18
18
 
@@ -29,9 +29,10 @@ module Trello
29
29
 
30
30
  def create(options)
31
31
  client.create(:list,
32
- 'name' => options[:name],
33
- 'idBoard' => options[:board_id],
34
- 'pos' => options[:pos])
32
+ 'name' => options[:name],
33
+ 'idBoard' => options[:board_id],
34
+ 'pos' => options[:pos],
35
+ 'idListSource' => options[:source_list_id])
35
36
  end
36
37
  end
37
38
 
@@ -40,11 +41,12 @@ module Trello
40
41
  # Supply a hash of string keyed data retrieved from the Trello API representing
41
42
  # a List.
42
43
  def update_fields(fields)
43
- attributes[:id] = fields['id']
44
- attributes[:name] = fields['name']
45
- attributes[:closed] = fields['closed']
46
- attributes[:board_id] = fields['idBoard']
47
- attributes[:pos] = fields['pos']
44
+ attributes[:id] = fields['id']
45
+ attributes[:name] = fields['name']
46
+ attributes[:closed] = fields['closed']
47
+ attributes[:board_id] = fields['idBoard']
48
+ attributes[:pos] = fields['pos']
49
+ attributes[:source_list_id] = fields['idListSource']
48
50
  self
49
51
  end
50
52
 
@@ -55,7 +57,8 @@ module Trello
55
57
  name: name,
56
58
  closed: closed || false,
57
59
  idBoard: board_id,
58
- pos: pos
60
+ pos: pos,
61
+ idListSource: source_list_id
59
62
  })
60
63
  end
61
64
 
@@ -98,6 +101,11 @@ module Trello
98
101
  })
99
102
  end
100
103
 
104
+ # Archives all the cards of the list
105
+ def archive_all_cards
106
+ client.post("/lists/#{id}/archiveAllCards")
107
+ end
108
+
101
109
  # :nodoc:
102
110
  def request_prefix
103
111
  "/lists/#{id}"
@@ -19,6 +19,7 @@ module Trello
19
19
  Response.new(200, {}, result)
20
20
  end
21
21
  rescue RestClient::Exception => e
22
+ raise if !e.respond_to?(:http_code) || e.http_code.nil?
22
23
  Response.new(e.http_code, {}, e.http_body)
23
24
  end
24
25
  end
@@ -130,12 +130,12 @@ module Trello
130
130
 
131
131
  expect(labels.count).to eq(4)
132
132
  expect(labels[2].color).to eq('red')
133
- expect(labels[2].id).to eq('abcdef123456789123456789')
133
+ expect(labels[2].id).to eq('cbcdef123456789123456789')
134
134
  expect(labels[2].board_id).to eq('abcdef123456789123456789')
135
135
  expect(labels[2].name).to eq('deploy')
136
136
  expect(labels[2].uses).to eq(2)
137
137
  expect(labels[3].color).to eq('blue')
138
- expect(labels[3].id).to eq('abcdef123456789123456789')
138
+ expect(labels[3].id).to eq('dbcdef123456789123456789')
139
139
  expect(labels[3].board_id).to eq('abcdef123456789123456789')
140
140
  expect(labels[3].name).to eq('on hold')
141
141
  expect(labels[3].uses).to eq(6)
@@ -94,7 +94,7 @@ module Trello
94
94
 
95
95
  expect(card).to be_a Card
96
96
  end
97
-
97
+
98
98
  it 'creates a duplicate card with source due date and checklists and saves it on Trello', refactor: true do
99
99
  payload = {
100
100
  source_card_id: cards_details.first['id'],
@@ -220,6 +220,16 @@ module Trello
220
220
  it "gets its pos" do
221
221
  expect(card.pos).to_not be_nil
222
222
  end
223
+
224
+
225
+ it 'gets its creation time' do
226
+ expect(card.created_at).to be_kind_of Time
227
+ end
228
+
229
+ it 'get its correct creation time' do
230
+ expect(card.created_at).to eq(Time.parse('2061-05-04 04:40:18 +0200'))
231
+ end
232
+
223
233
  end
224
234
 
225
235
  context "actions" do
@@ -402,6 +412,76 @@ module Trello
402
412
  end
403
413
  end
404
414
 
415
+ context "add/remove votes" do
416
+ let(:authenticated_member) { double(id: '4ee7df3ce582acdec80000b2') }
417
+
418
+ before do
419
+ allow(card)
420
+ .to receive(:me)
421
+ .and_return(authenticated_member)
422
+ end
423
+
424
+ it 'upvotes a card with the currently authenticated member' do
425
+ expect(client)
426
+ .to receive(:post)
427
+ .with("/cards/abcdef123456789123456789/membersVoted", {
428
+ value: authenticated_member.id
429
+ })
430
+
431
+ card.upvote
432
+ end
433
+
434
+ it 'returns the card even if the user has already upvoted' do
435
+ expect(client)
436
+ .to receive(:post)
437
+ .with("/cards/abcdef123456789123456789/membersVoted", {
438
+ value: authenticated_member.id
439
+ })
440
+ .and_raise(Trello::Error, 'member has already voted')
441
+ expect(card.upvote).to be_kind_of Trello::Card
442
+ end
443
+
444
+ it 'removes an upvote from a card' do
445
+ expect(client)
446
+ .to receive(:delete)
447
+ .with("/cards/abcdef123456789123456789/membersVoted/#{authenticated_member.id}")
448
+
449
+ card.remove_upvote
450
+ end
451
+
452
+ it 'returns card after remove_upvote even if the user has not previously upvoted it' do
453
+ expect(client)
454
+ .to receive(:delete)
455
+ .with("/cards/abcdef123456789123456789/membersVoted/#{authenticated_member.id}")
456
+ .and_raise(Trello::Error, 'member has not voted on the card')
457
+
458
+ card.remove_upvote
459
+ end
460
+
461
+ end
462
+
463
+ context "return all voters" do
464
+ it 'returns members that have voted for the card' do
465
+ no_voters = JSON.generate([])
466
+ expect(client)
467
+ .to receive(:get)
468
+ .with("/cards/#{card.id}/membersVoted")
469
+ .and_return(no_voters)
470
+
471
+ card.voters
472
+
473
+
474
+ voters = JSON.generate([user_details])
475
+ expect(client)
476
+ .to receive(:get)
477
+ .with("/cards/#{card.id}/membersVoted")
478
+ .and_return(voters)
479
+
480
+ expect(card.voters.first).to be_kind_of Trello::Member
481
+ end
482
+ end
483
+
484
+
405
485
  context "comments" do
406
486
  it "posts a comment" do
407
487
  expect(client)
@@ -415,37 +495,39 @@ module Trello
415
495
 
416
496
  context "labels" do
417
497
  before do
418
- allow(client)
419
- .to receive(:get)
420
- .with("/cards/abcdef123456789123456789/labels")
421
- .and_return label_payload
422
-
423
498
  allow(client)
424
499
  .to receive(:post)
425
- .with("/cards/abcdef123456789123456789/labels", { value: 'green' })
500
+ .with("/cards/ebcdef123456789123456789/labels", { value: 'green' })
426
501
  .and_return "not important"
427
502
 
428
503
  allow(client)
429
504
  .to receive(:delete)
430
- .with("/cards/abcdef123456789123456789/labels/green")
505
+ .with("/cards/ebcdef123456789123456789/labels/green")
431
506
  .and_return "not important"
432
507
  end
433
- it "can retrieve labels" do
434
- allow(client).to receive(:get).
435
- with("/cards/abcdef123456789123456789/labels", {}).
436
- and_return label_payload
508
+
509
+ it "includes card label objects list" do
437
510
  labels = card.labels
438
- expect(labels.size).to eq(4)
439
- expect(labels[0].color).to eq('yellow')
440
- expect(labels[0].id).to eq('abcdef123456789123456789')
441
- expect(labels[0].board_id).to eq('abcdef123456789123456789')
442
- expect(labels[0].name).to eq('iOS')
443
- expect(labels[0].uses).to eq(3)
444
- expect(labels[1].color).to eq('purple')
445
- expect(labels[1].id).to eq('abcdef123456789123456789')
446
- expect(labels[1].board_id).to eq('abcdef123456789123456789')
447
- expect(labels[1].name).to eq('Issue or bug')
448
- expect(labels[1].uses).to eq(1)
511
+ expect(labels.size).to eq(4)
512
+ expect(labels[0].color).to eq('yellow')
513
+ expect(labels[0].id).to eq('abcdef123456789123456789')
514
+ expect(labels[0].board_id).to eq('abcdef123456789123456789')
515
+ expect(labels[0].name).to eq('iOS')
516
+ expect(labels[0].uses).to eq(3)
517
+ expect(labels[1].color).to eq('purple')
518
+ expect(labels[1].id).to eq('bbcdef123456789123456789')
519
+ expect(labels[1].board_id).to eq('abcdef123456789123456789')
520
+ expect(labels[1].name).to eq('Issue or bug')
521
+ expect(labels[1].uses).to eq(1)
522
+ end
523
+
524
+ it "includes label ids list" do
525
+ label_ids = card.card_labels
526
+ expect(label_ids.size).to eq(4)
527
+ expect(label_ids[0]).to eq('abcdef123456789123456789')
528
+ expect(label_ids[1]).to eq('bbcdef123456789123456789')
529
+ expect(label_ids[2]).to eq('cbcdef123456789123456789')
530
+ expect(label_ids[3]).to eq('dbcdef123456789123456789')
449
531
  end
450
532
 
451
533
  it "can remove a label" do
@@ -139,6 +139,17 @@ module Trello
139
139
 
140
140
  checklist.add_item(expected_item_name, expected_checked, expected_pos)
141
141
  end
142
+
143
+ it "updates an item's state" do
144
+ expected_item_id = "1234"
145
+ expected_state = "incomplete"
146
+ expected_resource =
147
+ "/cards/abccardid/checklist/abcdef123456789123456789" \
148
+ "/checkItem/#{expected_item_id}/state"
149
+ payload = { value: expected_state }
150
+ expect(client).to receive(:put).once.with(expected_resource, payload)
151
+ checklist.update_item_state(expected_item_id, expected_state)
152
+ end
142
153
  end
143
154
 
144
155
  context "board" do
@@ -3,202 +3,255 @@ require "spec_helper"
3
3
  include Trello
4
4
  include Trello::Authorization
5
5
 
6
- describe Client, "and how it handles authorization" do
7
- let (:fake_ok_response) do
8
- double "A fake OK response",
9
- code: 200,
10
- body: "A fake response body"
11
- end
6
+ describe Client do
7
+
12
8
  let(:client) { Client.new }
13
9
  let(:auth_policy) { double }
14
10
 
15
11
  before do
16
- allow(TInternet)
17
- .to receive(:execute)
18
- .and_return fake_ok_response
19
-
20
12
  allow(Authorization::AuthPolicy)
21
13
  .to receive(:new)
22
- .and_return(auth_policy)
14
+ .and_return(auth_policy)
23
15
 
24
16
  allow(auth_policy)
25
17
  .to receive(:authorize) { |request| request }
26
18
  end
27
19
 
28
- it "authorizes before it queries the internet" do
29
- expect(auth_policy)
30
- .to receive(:authorize)
31
- .once
32
- .ordered
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 }
33
23
 
34
- expect(TInternet)
35
- .to receive(:execute)
36
- .once
37
- .ordered
24
+ before do
25
+ allow(TInternet)
26
+ .to receive(:execute_core)
27
+ .and_raise(rc_exception_without_http_code)
28
+ end
38
29
 
39
- client.get "/xxx"
40
- end
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
41
34
 
42
- it "queries the internet with expanded earl and query parameters" do
43
- expected_uri = Addressable::URI.parse("https://api.trello.com/1/xxx?a=1&b=2")
44
- expected_request = Request.new :get, expected_uri, {}
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"}))}
45
40
 
46
- expect(TInternet)
47
- .to receive(:execute)
48
- .once
49
- .with expected_request
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)
50
52
 
51
- client.get "/xxx", a: "1", b: "2"
53
+ expect { client.get "/xxx" }.to raise_error(Error, "404 error response")
54
+ end
55
+ end
52
56
  end
53
57
 
54
- it "encodes parameters" do
55
- expected_uri = Addressable::URI.parse("https://api.trello.com/1/xxx?name=Jazz%20Kang")
56
- expected_request = Request.new :get, expected_uri, {}
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
57
71
 
58
- expect(TInternet)
59
- .to receive(:execute)
60
- .once
61
- .with expected_request
72
+ allow(Authorization::AuthPolicy)
73
+ .to receive(:new)
74
+ .and_return(auth_policy)
62
75
 
63
- client.get "/xxx", name: "Jazz Kang"
64
- end
76
+ allow(auth_policy)
77
+ .to receive(:authorize) { |request| request }
78
+ end
65
79
 
66
- it "raises an error when response has non-200 status" do
67
- expected_error_message = "An error response"
68
- response_with_non_200_status = double "A fake OK response",
69
- code: 404,
70
- body: expected_error_message
80
+ it "authorizes before it queries the internet" do
81
+ expect(auth_policy)
82
+ .to receive(:authorize)
83
+ .once
84
+ .ordered
71
85
 
72
- expect(TInternet)
73
- .to receive(:execute)
74
- .and_return response_with_non_200_status
86
+ expect(TInternet)
87
+ .to receive(:execute)
88
+ .once
89
+ .ordered
75
90
 
76
- expect { client.get "/xxx" }.to raise_error expected_error_message
77
- end
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
78
117
 
79
- it "uses version 1 of the API" do
80
- expect(TInternet)
81
- .to receive(:execute)
82
- .once do |request|
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|
83
135
  expect(request.uri.to_s).to match(/1\//)
84
136
  fake_ok_response
85
137
  end
86
138
 
87
- client.get "/"
88
- end
139
+ client.get "/"
140
+ end
89
141
 
90
- it "omits the \"?\" when no parameters" do
91
- expect(TInternet)
92
- .to receive(:execute)
93
- .once do |request|
142
+ it "omits the \"?\" when no parameters" do
143
+ expect(TInternet)
144
+ .to receive(:execute)
145
+ .once do |request|
94
146
  expect(request.uri.to_s).not_to match(/\?$/)
95
147
  fake_ok_response
96
148
  end
97
149
 
98
- client.get "/xxx"
99
- end
150
+ client.get "/xxx"
151
+ end
100
152
 
101
- it "supports post" do
102
- expect(TInternet)
103
- .to receive(:execute)
104
- .once
105
- .and_return fake_ok_response
153
+ it "supports post" do
154
+ expect(TInternet)
155
+ .to receive(:execute)
156
+ .once
157
+ .and_return fake_ok_response
106
158
 
107
- client.post "/xxx", { phil: "T' north" }
108
- end
159
+ client.post "/xxx", { phil: "T' north" }
160
+ end
109
161
 
110
- it "supplies the body for a post" do
111
- expected_body = { name: "Phil", nickname: "The Crack Fox" }
162
+ it "supplies the body for a post" do
163
+ expected_body = { name: "Phil", nickname: "The Crack Fox" }
112
164
 
113
- expect(TInternet)
114
- .to receive(:execute)
115
- .once do |request|
165
+ expect(TInternet)
166
+ .to receive(:execute)
167
+ .once do |request|
116
168
  expect(request.body).to eq expected_body
117
169
  fake_ok_response
118
170
  end
119
171
 
120
- client.post "/xxx", expected_body
121
- end
172
+ client.post "/xxx", expected_body
173
+ end
122
174
 
123
- it "supplies the path for a post" do
124
- expected_path = "/xxx"
175
+ it "supplies the path for a post" do
176
+ expected_path = "/xxx"
125
177
 
126
- expect(TInternet)
127
- .to receive(:execute)
128
- .once do |request|
178
+ expect(TInternet)
179
+ .to receive(:execute)
180
+ .once do |request|
129
181
  expect(request.uri.path).to match(/#{expected_path}$/)
130
182
  fake_ok_response
131
183
  end
132
184
 
133
- client.post "/xxx", {}
134
- end
185
+ client.post "/xxx", {}
186
+ end
135
187
 
136
- it "supports put" do
137
- expect(TInternet)
138
- .to receive(:execute)
139
- .once
140
- .and_return fake_ok_response
188
+ it "supports put" do
189
+ expect(TInternet)
190
+ .to receive(:execute)
191
+ .once
192
+ .and_return fake_ok_response
141
193
 
142
- client.put "/xxx", { phil: "T' north" }
143
- end
194
+ client.put "/xxx", { phil: "T' north" }
195
+ end
144
196
 
145
- it "supplies the body for a put" do
146
- expected_body = { name: "Phil", nickname: "The Crack Fox" }
197
+ it "supplies the body for a put" do
198
+ expected_body = { name: "Phil", nickname: "The Crack Fox" }
147
199
 
148
- expect(TInternet)
149
- .to receive(:execute)
150
- .once do |request|
200
+ expect(TInternet)
201
+ .to receive(:execute)
202
+ .once do |request|
151
203
  expect(request.body).to eq expected_body
152
204
  fake_ok_response
153
205
  end
154
206
 
155
- client.put "/xxx", expected_body
156
- end
207
+ client.put "/xxx", expected_body
208
+ end
157
209
 
158
- it "supplies the path for a put" do
159
- expected_path = "/xxx"
210
+ it "supplies the path for a put" do
211
+ expected_path = "/xxx"
160
212
 
161
- expect(TInternet)
162
- .to receive(:execute)
163
- .once do |request|
213
+ expect(TInternet)
214
+ .to receive(:execute)
215
+ .once do |request|
164
216
  expect(request.uri.path).to match(/#{expected_path}$/)
165
217
  fake_ok_response
166
218
  end
167
219
 
168
- client.put "/xxx", {}
169
- end
170
-
171
- context "initialize" do
172
- let(:client) do
173
- Client.new(
174
- consumer_key: 'consumer_key',
175
- consumer_secret: 'consumer_secret',
176
- oauth_token: 'oauth_token',
177
- oauth_token_secret: 'oauth_token_secret'
178
- )
220
+ client.put "/xxx", {}
179
221
  end
180
222
 
181
- it "is configurable" do
182
- expect(client.consumer_key).to eq('consumer_key')
183
- expect(client.consumer_secret).to eq('consumer_secret')
184
- expect(client.oauth_token).to eq('oauth_token')
185
- expect(client.oauth_token_secret).to eq('oauth_token_secret')
186
- end
187
- end
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
188
232
 
189
- describe "configure" do
190
- it "sets key attributes through config block" do
191
- client.configure do |config|
192
- config.consumer_key = 'consumer_key'
193
- config.consumer_secret = 'consumer_secret'
194
- config.oauth_token = 'oauth_token'
195
- config.oauth_token_secret = 'oauth_token_secret'
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')
196
238
  end
239
+ end
197
240
 
198
- expect(client.consumer_key).to eq('consumer_key')
199
- expect(client.consumer_secret).to eq('consumer_secret')
200
- expect(client.oauth_token).to eq('oauth_token')
201
- expect(client.oauth_token_secret).to eq('oauth_token_secret')
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
202
255
  end
203
256
  end
204
257
  end
@@ -57,12 +57,19 @@ module Trello
57
57
  payload = {
58
58
  name: 'Test List',
59
59
  board_id: 'abcdef123456789123456789',
60
- pos: 42
60
+ pos: 42,
61
+ source_list_id: 'abcdef123456789'
61
62
  }
62
63
 
63
64
  result = JSON.generate(payload)
64
65
 
65
- expected_payload = {name: 'Test List', closed: false, idBoard: 'abcdef123456789123456789', pos: 42}
66
+ expected_payload = {
67
+ name: 'Test List',
68
+ closed: false,
69
+ idBoard: 'abcdef123456789123456789',
70
+ pos: 42,
71
+ idListSource: 'abcdef123456789'
72
+ }
66
73
 
67
74
  expect(client)
68
75
  .to receive(:post)
@@ -163,6 +170,15 @@ module Trello
163
170
 
164
171
  expect(list.move_all_cards(other_list)).to eq cards_payload
165
172
  end
173
+
174
+ it 'archives all cards' do
175
+ allow(client)
176
+ .to receive(:post)
177
+ .with('/lists/abcdef123456789123456789/archiveAllCards')
178
+ .and_return cards_payload
179
+
180
+ expect(list.archive_all_cards).to eq cards_payload
181
+ end
166
182
  end
167
183
 
168
184
  describe '#closed?' do
@@ -88,6 +88,7 @@ module Helpers
88
88
  'position' => 16384,
89
89
  'url' => 'https://trello.com/blah/blah',
90
90
  'idBoard' => 'abcdef123456789123456789',
91
+ 'idCard' => 'abccardid',
91
92
  'idList' => 'abcdef123456789123456789',
92
93
  'idMembers' => ['abcdef123456789123456789'],
93
94
  'checkItems' => { 'id' => 'ghijk987654321' }
@@ -142,6 +143,11 @@ module Helpers
142
143
  'idBoard' => 'abcdef123456789123456789',
143
144
  'idAttachmentCover' => 'abcdef123456789123456789',
144
145
  'idMembers' => ['abcdef123456789123456789'],
146
+ 'labels' => label_details,
147
+ 'idLabels' => [ 'abcdef123456789123456789',
148
+ 'bbcdef123456789123456789',
149
+ 'cbcdef123456789123456789',
150
+ 'dbcdef123456789123456789' ],
145
151
  'url' => 'https://trello.com/card/board/specify-the-type-and-scope-of-the-jit-in-a-lightweight-spec/abcdef123456789123456789/abcdef123456789123456789',
146
152
  'shortUrl' => 'https://trello.com/c/abcdef12',
147
153
  'pos' => 12,
@@ -310,9 +316,9 @@ module Helpers
310
316
  def label_details
311
317
  [
312
318
  {'color' => 'yellow', 'name' => 'iOS', 'id' => 'abcdef123456789123456789', 'uses' => 3, 'idBoard' => 'abcdef123456789123456789'},
313
- {'color' => 'purple', 'name' => 'Issue or bug', 'id' => 'abcdef123456789123456789', 'uses' => 1, 'idBoard' => 'abcdef123456789123456789'},
314
- {'color' => 'red', 'name' => 'deploy', 'id' => 'abcdef123456789123456789', 'uses' => 2, 'idBoard' => 'abcdef123456789123456789'},
315
- {'color' => 'blue', 'name' => 'on hold', 'id' => 'abcdef123456789123456789', 'uses' => 6, 'idBoard' => 'abcdef123456789123456789'}
319
+ {'color' => 'purple', 'name' => 'Issue or bug', 'id' => 'bbcdef123456789123456789', 'uses' => 1, 'idBoard' => 'abcdef123456789123456789'},
320
+ {'color' => 'red', 'name' => 'deploy', 'id' => 'cbcdef123456789123456789', 'uses' => 2, 'idBoard' => 'abcdef123456789123456789'},
321
+ {'color' => 'blue', 'name' => 'on hold', 'id' => 'dbcdef123456789123456789', 'uses' => 6, 'idBoard' => 'abcdef123456789123456789'}
316
322
  ]
317
323
  end
318
324
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-trello
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.2
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Tregunna
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-10 00:00:00.000000000 Z
11
+ date: 2016-08-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -56,14 +56,14 @@ dependencies:
56
56
  name: oauth
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: 0.4.5
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: 0.4.5
69
69
  - !ruby/object:Gem::Dependency
@@ -158,7 +158,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
158
158
  requirements:
159
159
  - - ">="
160
160
  - !ruby/object:Gem::Version
161
- version: 2.0.0
161
+ version: 2.1.0
162
162
  required_rubygems_version: !ruby/object:Gem::Requirement
163
163
  requirements:
164
164
  - - ">="