ruby-trello 1.4.2 → 1.5.1

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 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
  - - ">="